1
1
// go-rs/rest-api-framework
2
- // Copyright(c) 2019 Roshan Gade. All rights reserved.
2
+ // Copyright(c) 2019 Roshan Gade. All rights reserved.
3
3
// MIT Licensed
4
4
5
5
package rest
6
6
7
7
import (
8
+ "log"
8
9
"net/http"
9
10
"net/url"
10
11
11
12
"github.com/go-rs/rest-api-framework/render"
12
13
)
13
14
15
+ // Task, which is used to perform a specific job,
16
+ // just before request completion or after request completion
14
17
type Task func ()
15
18
16
- /**
17
- * Context
18
- */
19
+ // Context, which initializes at every request with pre-declared variables
20
+ // such as Request, Response, Query, Body, Params etc.
19
21
type Context struct {
20
- Request * http.Request
21
- Response http.ResponseWriter
22
- Query url.Values
23
- Body interface {}
24
- Params map [string ]string
22
+ // available to users
23
+ Request * http.Request
24
+ Response http.ResponseWriter
25
+ Query url.Values
26
+ Body interface {}
27
+ Params map [string ]string
28
+
29
+ // for internal use
25
30
headers map [string ]string
26
31
data map [string ]interface {}
27
32
err error
@@ -35,150 +40,134 @@ type Context struct {
35
40
postSendTasks []Task
36
41
}
37
42
38
- /**
39
- * Initialization of context on every request
40
- */
43
+ // Initialization of context data on every request
41
44
func (ctx * Context ) init () {
42
45
ctx .headers = make (map [string ]string )
43
46
ctx .data = make (map [string ]interface {})
44
47
ctx .preSendTasks = make ([]Task , 0 )
45
48
ctx .postSendTasks = make ([]Task , 0 )
46
49
ctx .status = 200
47
- ctx .found = false
48
- ctx .end = false
49
50
}
50
51
51
- /**
52
- * Destroy context once request end
53
- */
52
+ // Destroy context data once request end
54
53
func (ctx * Context ) destroy () {
55
54
ctx .Request = nil
56
55
ctx .Response = nil
56
+ ctx .Query = nil
57
+ ctx .Body = nil
57
58
ctx .Params = nil
59
+ ctx .headers = nil
58
60
ctx .data = nil
59
61
ctx .err = nil
60
62
ctx .status = 0
61
63
ctx .found = false
62
64
ctx .end = false
65
+ ctx .requestSent = false
66
+ ctx .preTasksCalled = false
67
+ ctx .postTasksCalled = false
68
+ ctx .preSendTasks = nil
69
+ ctx .postSendTasks = nil
63
70
}
64
71
65
- /**
66
- * Set request data in context
67
- */
72
+ // Set data
68
73
func (ctx * Context ) Set (key string , val interface {}) {
69
74
ctx .data [key ] = val
70
75
}
71
76
72
- /**
73
- * Get request data from context
74
- */
77
+ // Get data
75
78
func (ctx * Context ) Get (key string ) (val interface {}, exists bool ) {
76
- val = ctx .data [key ]
77
- exists = val != nil
79
+ val , exists = ctx .data [key ]
78
80
return
79
81
}
80
82
81
- /**
82
- * Set Status
83
- */
83
+ // Delete data
84
+ func (ctx * Context ) Delete (key string , val interface {}) {
85
+ delete (ctx .data , key )
86
+ }
87
+
88
+ // Set response status
84
89
func (ctx * Context ) Status (code int ) * Context {
85
90
ctx .status = code
86
91
return ctx
87
92
}
88
93
89
- /**
90
- * Set Header
91
- */
94
+ // Set response header
92
95
func (ctx * Context ) SetHeader (key string , val string ) * Context {
93
96
ctx .headers [key ] = val
94
97
return ctx
95
98
}
96
99
97
- /**
98
- * Throw error
99
- */
100
+ // Caught error in context on throw
100
101
func (ctx * Context ) Throw (err error ) {
101
102
ctx .err = err
102
103
}
103
104
104
- /**
105
- * Get error
106
- */
105
+ // Get error if any
107
106
func (ctx * Context ) GetError () error {
108
107
return ctx .err
109
108
}
110
109
111
- /**
112
- * End
113
- */
110
+ // Marked the request is ended
114
111
func (ctx * Context ) End () {
115
112
ctx .end = true
116
113
}
117
114
118
- /**
119
- * Write Bytes
120
- */
115
+ // Send response in bytes
121
116
func (ctx * Context ) Write (data []byte ) {
122
117
ctx .send (data , nil )
123
118
}
124
119
125
- /**
126
- * Write JSON
127
- */
120
+ // Send JSON data in response
128
121
func (ctx * Context ) JSON (data interface {}) {
129
122
json := render.JSON {
130
123
Body : data ,
131
124
}
132
- body , err := json .Write (ctx .Response )
125
+ body , err := json .ToBytes (ctx .Response )
133
126
ctx .send (body , err )
134
127
}
135
128
136
- /**
137
- * Write Text
138
- */
129
+ // Send text in response
139
130
func (ctx * Context ) Text (data string ) {
140
131
txt := render.Text {
141
132
Body : data ,
142
133
}
143
- body , err := txt .Write (ctx .Response )
134
+ body , err := txt .ToBytes (ctx .Response )
144
135
ctx .send (body , err )
145
136
}
146
137
147
- /**
148
- *
149
- */
138
+ // Register pre-send hook
150
139
func (ctx * Context ) PreSend (task Task ) {
151
140
ctx .preSendTasks = append (ctx .preSendTasks , task )
152
141
}
153
142
154
- /**
155
- *
156
- */
143
+ // Register pre-post hook
157
144
func (ctx * Context ) PostSend (task Task ) {
158
145
ctx .postSendTasks = append (ctx .postSendTasks , task )
159
146
}
160
147
161
148
//////////////////////////////////////////////////
162
- /**
163
- * Send data
164
- */
149
+ // Send data, which uses bytes or error if any
150
+ // Also, it calls pre-send and post-send registered hooks
165
151
func (ctx * Context ) send (data []byte , err error ) {
166
152
if ctx .end {
167
153
return
168
154
}
169
155
170
156
if err != nil {
171
157
ctx .err = err
158
+ ctx .unhandledException ()
172
159
return
173
160
}
174
161
162
+ // execute pre-send hooks
175
163
if ! ctx .preTasksCalled {
176
164
ctx .preTasksCalled = true
177
165
for _ , task := range ctx .preSendTasks {
178
166
task ()
179
167
}
180
168
}
181
169
170
+ // write data
182
171
if ! ctx .requestSent {
183
172
ctx .requestSent = true
184
173
@@ -191,11 +180,12 @@ func (ctx *Context) send(data []byte, err error) {
191
180
_ , err = ctx .Response .Write (data )
192
181
193
182
if err != nil {
194
- ctx . err = err
195
- return
183
+ //TODO: debugger mode
184
+ log . Println ( "Response Error: " , err )
196
185
}
197
186
}
198
187
188
+ // execute post-send hooks
199
189
if ! ctx .postTasksCalled {
200
190
ctx .postTasksCalled = true
201
191
for _ , task := range ctx .postSendTasks {
@@ -206,13 +196,13 @@ func (ctx *Context) send(data []byte, err error) {
206
196
ctx .End ()
207
197
}
208
198
209
- /**
210
- * Unhandled Exception
211
- */
199
+ // Unhandled Exception
212
200
func (ctx * Context ) unhandledException () {
213
201
defer func () {
214
202
err := recover ()
215
203
if err != nil {
204
+ //TODO: debugger mode
205
+ log .Println ("Unhandled Error: " , err )
216
206
if ! ctx .requestSent {
217
207
ctx .Response .WriteHeader (http .StatusInternalServerError )
218
208
ctx .Response .Header ().Set ("Content-Type" , "text/plain;charset=UTF-8" )
0 commit comments