Skip to content

Commit 8282f83

Browse files
authored
Merge pull request #1 from go-rs/develop
0.0.1-alpha.1
2 parents f6628b9 + d48342e commit 8282f83

File tree

12 files changed

+656
-7
lines changed

12 files changed

+656
-7
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@
1010

1111
# Output of the go coverage tool, specifically when used with LiteIDE
1212
*.out
13+
14+
# editors
15+
.idea
16+
.DS_Store
17+
.vscode

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Roshan Gade
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@ REST API framework for go lang
33

44
# Framework is under development
55
## Status:
6-
- Working on POC as per concept
6+
Released alpha version
7+
<br>
8+
See examples
9+
- Request Interceptors/Middlewares
10+
- Routes with URL pattern
11+
- Methods [GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH]
12+
- Extend routes with namespace
13+
- Error handler
14+
- HTTP, HTTPS support
15+
716
```
817
var api rest.API
918
@@ -13,22 +22,22 @@ api.Use(func(ctx *rest.Context) {
1322
})
1423
1524
// routes
16-
api.GET("/", func(ctx *rest.Context) {
17-
ctx.Send("Hello World!")
25+
api.Get("/", func(ctx *rest.Context) {
26+
ctx.Text("Hello World!")
1827
})
1928
20-
api.GET("/foo", func(ctx *rest.Context) {
29+
api.Get("/foo", func(ctx *rest.Context) {
2130
ctx.Status(401).Throw(errors.New("UNAUTHORIZED"))
2231
})
2332
24-
api.GET("/:bar", func(ctx *rest.Context) {
33+
api.Get("/:bar", func(ctx *rest.Context) {
2534
fmt.Println("authtoken", ctx.Get("authtoken"))
26-
ctx.SendJSON(ctx.Params)
35+
ctx.JSON(ctx.Params)
2736
})
2837
2938
// error handler
3039
api.Error("UNAUTHORIZED", func(ctx *rest.Context) {
31-
ctx.Send("You are unauthorized")
40+
ctx.Text("You are unauthorized")
3241
})
3342
3443
fmt.Println("Starting server.")

api.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*!
2+
* rest-api-framework
3+
* Copyright(c) 2019 Roshan Gade
4+
* MIT Licensed
5+
*/
6+
package rest
7+
8+
import (
9+
"errors"
10+
"fmt"
11+
"github.com/go-rs/rest-api-framework/utils"
12+
"net/http"
13+
"regexp"
14+
)
15+
16+
type Handler func(ctx *Context)
17+
18+
/**
19+
* API - Application
20+
*/
21+
type API struct {
22+
prefix string
23+
routes []route
24+
interceptors []interceptor
25+
exceptions []exception
26+
unhandled Handler
27+
}
28+
29+
/**
30+
* Route
31+
*/
32+
type route struct {
33+
method string
34+
pattern string
35+
regex *regexp.Regexp
36+
params []string
37+
handle Handler
38+
}
39+
40+
/**
41+
* Request interceptor
42+
*/
43+
type interceptor struct {
44+
handle Handler
45+
}
46+
47+
/**
48+
* Exception Route
49+
*/
50+
type exception struct {
51+
message string
52+
handle Handler
53+
}
54+
55+
/**
56+
* Common Route
57+
*/
58+
func (api *API) Route(method string, pattern string, handle Handler) {
59+
regex, params, err := utils.Compile(pattern)
60+
if err != nil {
61+
fmt.Println("Error in pattern", err)
62+
panic(1)
63+
}
64+
api.routes = append(api.routes, route{
65+
method: method,
66+
pattern: pattern,
67+
regex: regex,
68+
params: params,
69+
handle: handle,
70+
})
71+
}
72+
73+
/**
74+
* Required handle for http module
75+
*/
76+
func (api API) ServeHTTP(res http.ResponseWriter, req *http.Request) {
77+
78+
urlPath := []byte(req.URL.Path)
79+
80+
ctx := Context{
81+
Request: req,
82+
Response: res,
83+
}
84+
85+
// STEP 1: initialize context
86+
ctx.init()
87+
defer ctx.destroy()
88+
89+
// STEP 2: execute all interceptors
90+
for _, task := range api.interceptors {
91+
if ctx.end || ctx.err != nil {
92+
break
93+
}
94+
95+
task.handle(&ctx)
96+
}
97+
98+
// STEP 3: check routes
99+
for _, route := range api.routes {
100+
if ctx.end || ctx.err != nil {
101+
break
102+
}
103+
104+
if (route.method == "" || route.method == req.Method) && route.regex.Match(urlPath) {
105+
ctx.found = route.method != "" //?
106+
ctx.Params = utils.Exec(route.regex, route.params, urlPath)
107+
route.handle(&ctx)
108+
}
109+
}
110+
111+
// STEP 4: check handled exceptions
112+
for _, exp := range api.exceptions {
113+
if ctx.end || ctx.err == nil {
114+
break
115+
}
116+
117+
if exp.message == ctx.err.Error() {
118+
exp.handle(&ctx)
119+
}
120+
}
121+
122+
// STEP 5: unhandled exceptions
123+
if !ctx.end {
124+
if ctx.err == nil && !ctx.found {
125+
ctx.err = errors.New("URL_NOT_FOUND")
126+
}
127+
128+
if api.unhandled != nil {
129+
api.unhandled(&ctx)
130+
}
131+
}
132+
133+
// STEP 6: system handle
134+
if !ctx.end {
135+
ctx.unhandledException()
136+
}
137+
}
138+
139+
func (api *API) Use(handle Handler) {
140+
task := interceptor{
141+
handle: handle,
142+
}
143+
api.interceptors = append(api.interceptors, task)
144+
}
145+
146+
func (api *API) All(pattern string, handle Handler) {
147+
api.Route("", pattern, handle)
148+
}
149+
150+
func (api *API) Get(pattern string, handle Handler) {
151+
api.Route("GET", pattern, handle)
152+
}
153+
154+
func (api *API) Post(pattern string, handle Handler) {
155+
api.Route("POST", pattern, handle)
156+
}
157+
158+
func (api *API) Put(pattern string, handle Handler) {
159+
api.Route("PUT", pattern, handle)
160+
}
161+
162+
func (api *API) Delete(pattern string, handle Handler) {
163+
api.Route("DELETE", pattern, handle)
164+
}
165+
166+
func (api *API) Options(pattern string, handle Handler) {
167+
api.Route("OPTIONS", pattern, handle)
168+
}
169+
170+
func (api *API) Head(pattern string, handle Handler) {
171+
api.Route("HEAD", pattern, handle)
172+
}
173+
174+
func (api *API) Patch(pattern string, handle Handler) {
175+
api.Route("PATCH", pattern, handle)
176+
}
177+
178+
func (api *API) Exception(err string, handle Handler) {
179+
exp := exception{
180+
message: err,
181+
handle: handle,
182+
}
183+
api.exceptions = append(api.exceptions, exp)
184+
}
185+
186+
func (api *API) UnhandledException(handle Handler) {
187+
api.unhandled = handle
188+
}

0 commit comments

Comments
 (0)