11/*!
2- * utils -api-framework
2+ * rest -api-framework
33 * Copyright(c) 2019 Roshan Gade
44 * MIT Licensed
55 */
66package rest
77
88import (
99 "./utils"
10+ "errors"
1011 "fmt"
1112 "net/http"
1213 "regexp"
1314)
1415
16+ /**
17+ * API - Application
18+ */
1519type API struct {
1620 routes []route
1721 interceptors []interceptor
18- errors []errorHandler
22+ exceptions []exception
23+ unhandled func (ctx * Context )
1924}
2025
26+ /**
27+ * Route
28+ */
2129type route struct {
2230 method string
2331 pattern string
@@ -26,17 +34,25 @@ type route struct {
2634 handle func (ctx * Context )
2735}
2836
37+ /**
38+ * Request interceptor
39+ */
2940type interceptor struct {
3041 handle func (ctx * Context )
3142}
3243
33- //TODO: check errors in language specifications
34- type errorHandler struct {
35- code string
36- handle func (ctx * Context )
44+ /**
45+ * Exception Route
46+ */
47+ type exception struct {
48+ message string
49+ handle func (ctx * Context )
3750}
3851
39- func (api * API ) handler (method string , pattern string , handle func (ctx * Context )) {
52+ /**
53+ * Common Route
54+ */
55+ func (api * API ) Route (method string , pattern string , handle func (ctx * Context )) {
4056 regex , params , err := utils .Compile (pattern )
4157 if err != nil {
4258 fmt .Println ("Error in pattern" , err )
@@ -51,79 +67,115 @@ func (api *API) handler(method string, pattern string, handle func(ctx *Context)
5167 })
5268}
5369
70+ /**
71+ * Required handle for http module
72+ */
5473func (api API ) ServeHTTP (res http.ResponseWriter , req * http.Request ) {
55- //fmt.Println("-------------------------------------")
56- //fmt.Println("URI: ", req.RequestURI)
57- //fmt.Println("Method: ", req.Method)
58- //fmt.Println("Form: ", req.Form)
59- //fmt.Println("RawPath: ", req.URL.RawPath)
60- //fmt.Println("Header: ", req.Header)
61- //fmt.Println("Path: ", req.URL.Path)
62- //fmt.Println("RawQuery: ", req.URL.RawQuery)
63- //fmt.Println("Opaque: ", req.URL.Opaque)
64- //fmt.Println("-------------------------------------")
74+
6575 urlPath := []byte (req .URL .Path )
6676
6777 ctx := Context {
68- req : req ,
69- res : res ,
78+ Request : req ,
79+ Response : res ,
7080 }
7181
82+ // STEP 1: initialize context
7283 ctx .init ()
84+ defer ctx .destroy ()
7385
74- for _ , route := range api .interceptors {
75- if ctx .err != nil {
76- break
77- }
78-
79- if ctx .end == true {
86+ // STEP 2: execute all interceptors
87+ for _ , task := range api .interceptors {
88+ if ctx .end || ctx .err != nil {
8089 break
8190 }
8291
83- route .handle (& ctx )
92+ task .handle (& ctx )
8493 }
8594
95+ // STEP 3: check routes
8696 for _ , route := range api .routes {
87- if ctx .err != nil {
88- break
89- }
90-
91- if ctx .end == true {
97+ if ctx .end || ctx .err != nil {
9298 break
9399 }
94100
95101 if route .method == req .Method && route .regex .Match (urlPath ) {
102+ ctx .found = true
96103 ctx .Params = utils .Exec (route .regex , route .params , urlPath )
97104 route .handle (& ctx )
98105 }
99106 }
100107
101- //TODO: NOT FOUND, INTERNAL SERVER ERROR, ETC
102-
103- for _ , route := range api .errors {
104- if ctx .end == true {
108+ // STEP 4: check handled exceptions
109+ for _ , exp := range api .exceptions {
110+ if ctx .end || ctx .err == nil {
105111 break
106112 }
107113
108- if ctx .err != nil && route .code == ctx .err .Error () {
109- route .handle (& ctx )
114+ if exp .message == ctx .err .Error () {
115+ exp .handle (& ctx )
116+ }
117+ }
118+
119+ // STEP 5: unhandled exceptions
120+ if ! ctx .end {
121+ if ctx .err == nil && ! ctx .found {
122+ ctx .err = errors .New ("URL_NOT_FOUND" )
123+ }
124+
125+ if api .unhandled != nil {
126+ api .unhandled (& ctx )
110127 }
111128 }
129+
130+ // STEP 6: system handle
131+ if ! ctx .end {
132+ ctx .unhandledException ()
133+ }
112134}
113135
114136func (api * API ) Use (handle func (ctx * Context )) {
115- api .interceptors = append (api .interceptors , interceptor {handle : handle })
137+ task := interceptor {
138+ handle : handle ,
139+ }
140+ api .interceptors = append (api .interceptors , task )
116141}
117142
118143func (api * API ) GET (pattern string , handle func (ctx * Context )) {
119- api .handler ("GET" , pattern , handle )
144+ api .Route ("GET" , pattern , handle )
120145}
121146
122- //TODO: POST, PUT, DELETE, OPTIONS, HEAD, PATCH
147+ func (api * API ) POST (pattern string , handle func (ctx * Context )) {
148+ api .Route ("POST" , pattern , handle )
149+ }
123150
124- func (api * API ) Error (code string , handle func (ctx * Context )) {
125- api .errors = append (api .errors , errorHandler {
126- code : code ,
127- handle : handle ,
128- })
151+ func (api * API ) PUT (pattern string , handle func (ctx * Context )) {
152+ api .Route ("PUT" , pattern , handle )
153+ }
154+
155+ func (api * API ) DELETE (pattern string , handle func (ctx * Context )) {
156+ api .Route ("DELETE" , pattern , handle )
157+ }
158+
159+ func (api * API ) OPTIONS (pattern string , handle func (ctx * Context )) {
160+ api .Route ("OPTIONS" , pattern , handle )
161+ }
162+
163+ func (api * API ) HEAD (pattern string , handle func (ctx * Context )) {
164+ api .Route ("HEAD" , pattern , handle )
165+ }
166+
167+ func (api * API ) PATCH (pattern string , handle func (ctx * Context )) {
168+ api .Route ("PATCH" , pattern , handle )
169+ }
170+
171+ func (api * API ) Exception (err string , handle func (ctx * Context )) {
172+ exp := exception {
173+ message : err ,
174+ handle : handle ,
175+ }
176+ api .exceptions = append (api .exceptions , exp )
177+ }
178+
179+ func (api * API ) UnhandledException (handle func (ctx * Context )) {
180+ api .unhandled = handle
129181}
0 commit comments