@@ -25,6 +25,7 @@ type ContextNoBody = ContextWithBody[any]
25
25
// Please do not use a pointer type as parameter.
26
26
type ContextWithBody [B any ] interface {
27
27
context.Context
28
+
28
29
// Body returns the body of the request.
29
30
// If (*B) implements [InTransformer], it will be transformed after deserialization.
30
31
// It caches the result, so it can be called multiple times.
@@ -94,17 +95,9 @@ type ContextWithBody[B any] interface {
94
95
Redirect (code int , url string ) (any , error )
95
96
}
96
97
97
- // NewContextWithBody returns a new context. It is used internally by Fuego. You probably want to use Ctx[B] instead.
98
- func NewContextWithBody [B any ](w http.ResponseWriter , r * http.Request , options readOptions ) ContextWithBody [B ] {
99
- c := & contextWithBodyImpl [B ]{
100
- contextNoBodyImpl : NewContextNoBody (w , r , options ),
101
- }
102
-
103
- return c
104
- }
105
-
106
- func NewContextNoBody (w http.ResponseWriter , r * http.Request , options readOptions ) contextNoBodyImpl {
107
- c := contextNoBodyImpl {
98
+ // NewNetHTTPContext returns a new context. It is used internally by Fuego. You probably want to use Ctx[B] instead.
99
+ func NewNetHTTPContext [B any ](w http.ResponseWriter , r * http.Request , options readOptions ) ContextWithBody [B ] {
100
+ c := & netHttpContext [B ]{
108
101
Res : w ,
109
102
Req : r ,
110
103
readOptions : readOptions {
@@ -113,25 +106,21 @@ func NewContextNoBody(w http.ResponseWriter, r *http.Request, options readOption
113
106
},
114
107
urlValues : r .URL .Query (),
115
108
}
109
+
116
110
return c
117
111
}
118
112
113
+ var (
114
+ _ ContextWithBody [any ] = & netHttpContext [any ]{} // Check that ContextWithBody implements Ctx.
115
+ _ ContextWithBody [string ] = & netHttpContext [string ]{} // Check that ContextWithBody implements Ctx.
116
+ )
117
+
119
118
// ContextWithBody is the same as fuego.ContextNoBody, but
120
119
// has a Body. The Body type parameter represents the expected data type
121
120
// from http.Request.Body. Please do not use a pointer as a type parameter.
122
- type contextWithBodyImpl [Body any ] struct {
121
+ type netHttpContext [Body any ] struct {
123
122
body * Body // Cache the body in request context, because it is not possible to read an HTTP request body multiple times.
124
- contextNoBodyImpl
125
- }
126
-
127
- var (
128
- _ ContextWithBody [any ] = & contextWithBodyImpl [any ]{} // Check that ContextWithBody implements Ctx.
129
- _ ContextWithBody [string ] = & contextWithBodyImpl [string ]{} // Check that ContextWithBody implements Ctx.
130
- )
131
123
132
- // ContextNoBody is used when the controller does not have a body.
133
- // It is used as a base context for other Context types.
134
- type contextNoBodyImpl struct {
135
124
Req * http.Request
136
125
Res http.ResponseWriter
137
126
@@ -144,27 +133,9 @@ type contextNoBodyImpl struct {
144
133
readOptions readOptions
145
134
}
146
135
147
- var (
148
- _ ContextWithBody [any ] = contextNoBodyImpl {} // Check that ContextNoBody implements Ctx.
149
- _ context.Context = contextNoBodyImpl {} // Check that ContextNoBody implements context.Context.
150
- )
151
-
152
- func (c contextNoBodyImpl ) Body () (any , error ) {
153
- slog .Warn ("this method should not be called. It probably happened because you passed the context to another controller." )
154
- return body [map [string ]any ](c )
155
- }
156
-
157
- func (c contextNoBodyImpl ) MustBody () any {
158
- b , err := c .Body ()
159
- if err != nil {
160
- panic (err )
161
- }
162
- return b
163
- }
164
-
165
136
// SetStatus sets the status code of the response.
166
137
// Alias to http.ResponseWriter.WriteHeader.
167
- func (c contextNoBodyImpl ) SetStatus (code int ) {
138
+ func (c netHttpContext [ B ] ) SetStatus (code int ) {
168
139
c .Res .WriteHeader (code )
169
140
}
170
141
@@ -175,65 +146,65 @@ type readOptions struct {
175
146
LogBody bool
176
147
}
177
148
178
- func (c contextNoBodyImpl ) Redirect (code int , url string ) (any , error ) {
149
+ func (c netHttpContext [ B ] ) Redirect (code int , url string ) (any , error ) {
179
150
http .Redirect (c .Res , c .Req , url , code )
180
151
181
152
return nil , nil
182
153
}
183
154
184
155
// ContextNoBody implements the context interface via [net/http.Request.Context]
185
- func (c contextNoBodyImpl ) Deadline () (deadline time.Time , ok bool ) {
156
+ func (c netHttpContext [ B ] ) Deadline () (deadline time.Time , ok bool ) {
186
157
return c .Req .Context ().Deadline ()
187
158
}
188
159
189
160
// ContextNoBody implements the context interface via [net/http.Request.Context]
190
- func (c contextNoBodyImpl ) Done () <- chan struct {} {
161
+ func (c netHttpContext [ B ] ) Done () <- chan struct {} {
191
162
return c .Req .Context ().Done ()
192
163
}
193
164
194
165
// ContextNoBody implements the context interface via [net/http.Request.Context]
195
- func (c contextNoBodyImpl ) Err () error {
166
+ func (c netHttpContext [ B ] ) Err () error {
196
167
return c .Req .Context ().Err ()
197
168
}
198
169
199
170
// ContextNoBody implements the context interface via [net/http.Request.Context]
200
- func (c contextNoBodyImpl ) Value (key any ) any {
171
+ func (c netHttpContext [ B ] ) Value (key any ) any {
201
172
return c .Req .Context ().Value (key )
202
173
}
203
174
204
175
// ContextNoBody implements the context interface via [net/http.Request.Context]
205
- func (c contextNoBodyImpl ) Context () context.Context {
176
+ func (c netHttpContext [ B ] ) Context () context.Context {
206
177
return c .Req .Context ()
207
178
}
208
179
209
180
// Get request header
210
- func (c contextNoBodyImpl ) Header (key string ) string {
181
+ func (c netHttpContext [ B ] ) Header (key string ) string {
211
182
return c .Request ().Header .Get (key )
212
183
}
213
184
214
185
// Has request header
215
- func (c contextNoBodyImpl ) HasHeader (key string ) bool {
186
+ func (c netHttpContext [ B ] ) HasHeader (key string ) bool {
216
187
return c .Header (key ) != ""
217
188
}
218
189
219
190
// Sets response header
220
- func (c contextNoBodyImpl ) SetHeader (key , value string ) {
191
+ func (c netHttpContext [ B ] ) SetHeader (key , value string ) {
221
192
c .Response ().Header ().Set (key , value )
222
193
}
223
194
224
195
// Get request cookie
225
- func (c contextNoBodyImpl ) Cookie (name string ) (* http.Cookie , error ) {
196
+ func (c netHttpContext [ B ] ) Cookie (name string ) (* http.Cookie , error ) {
226
197
return c .Request ().Cookie (name )
227
198
}
228
199
229
200
// Has request cookie
230
- func (c contextNoBodyImpl ) HasCookie (name string ) bool {
201
+ func (c netHttpContext [ B ] ) HasCookie (name string ) bool {
231
202
_ , err := c .Cookie (name )
232
203
return err == nil
233
204
}
234
205
235
206
// Sets response cookie
236
- func (c contextNoBodyImpl ) SetCookie (cookie http.Cookie ) {
207
+ func (c netHttpContext [ B ] ) SetCookie (cookie http.Cookie ) {
237
208
http .SetCookie (c .Response (), & cookie )
238
209
}
239
210
@@ -245,7 +216,7 @@ func (c contextNoBodyImpl) SetCookie(cookie http.Cookie) {
245
216
// that the templates will be parsed only once, removing
246
217
// the need to parse the templates on each request but also preventing
247
218
// to dynamically use new templates.
248
- func (c contextNoBodyImpl ) Render (templateToExecute string , data any , layoutsGlobs ... string ) (CtxRenderer , error ) {
219
+ func (c netHttpContext [ B ] ) Render (templateToExecute string , data any , layoutsGlobs ... string ) (CtxRenderer , error ) {
249
220
return & StdRenderer {
250
221
templateToExecute : templateToExecute ,
251
222
templates : c .templates ,
@@ -256,7 +227,7 @@ func (c contextNoBodyImpl) Render(templateToExecute string, data any, layoutsGlo
256
227
}
257
228
258
229
// PathParams returns the path parameters of the request.
259
- func (c contextNoBodyImpl ) PathParam (name string ) string {
230
+ func (c netHttpContext [ B ] ) PathParam (name string ) string {
260
231
return c .Req .PathValue (name )
261
232
}
262
233
@@ -280,12 +251,12 @@ func (e QueryParamInvalidTypeError) Error() string {
280
251
}
281
252
282
253
// QueryParams returns the query parameters of the request. It is a shortcut for c.Req.URL.Query().
283
- func (c contextNoBodyImpl ) QueryParams () url.Values {
254
+ func (c netHttpContext [ B ] ) QueryParams () url.Values {
284
255
return c .urlValues
285
256
}
286
257
287
258
// QueryParamsArr returns an slice of string from the given query parameter.
288
- func (c contextNoBodyImpl ) QueryParamArr (name string ) []string {
259
+ func (c netHttpContext [ B ] ) QueryParamArr (name string ) []string {
289
260
_ , ok := c .params [name ]
290
261
if ! ok {
291
262
slog .Warn ("query parameter not expected in OpenAPI spec" , "param" , name )
@@ -301,7 +272,7 @@ func (c contextNoBodyImpl) QueryParamArr(name string) []string {
301
272
// fuego.Get(s, "/test", myController,
302
273
// option.Query("name", "Name", param.Default("hey"))
303
274
// )
304
- func (c contextNoBodyImpl ) QueryParam (name string ) string {
275
+ func (c netHttpContext [ B ] ) QueryParam (name string ) string {
305
276
_ , ok := c .params [name ]
306
277
if ! ok {
307
278
slog .Warn ("query parameter not expected in OpenAPI spec" , "param" , name , "expected_one_of" , c .params )
@@ -314,7 +285,7 @@ func (c contextNoBodyImpl) QueryParam(name string) string {
314
285
return c .urlValues .Get (name )
315
286
}
316
287
317
- func (c contextNoBodyImpl ) QueryParamIntErr (name string ) (int , error ) {
288
+ func (c netHttpContext [ B ] ) QueryParamIntErr (name string ) (int , error ) {
318
289
param := c .QueryParam (name )
319
290
if param == "" {
320
291
defaultValue , ok := c .params [name ].Default .(int )
@@ -348,7 +319,7 @@ func (c contextNoBodyImpl) QueryParamIntErr(name string) (int, error) {
348
319
//
349
320
// and the query parameter does not exist, it will return 1.
350
321
// If the query parameter does not exist and there is no default value, or if it is not an int, it returns 0.
351
- func (c contextNoBodyImpl ) QueryParamInt (name string ) int {
322
+ func (c netHttpContext [ B ] ) QueryParamInt (name string ) int {
352
323
param , err := c .QueryParamIntErr (name )
353
324
if err != nil {
354
325
return 0
@@ -367,7 +338,7 @@ func (c contextNoBodyImpl) QueryParamInt(name string) int {
367
338
//
368
339
// and the query parameter does not exist in the HTTP request, it will return true.
369
340
// Accepted values are defined as [strconv.ParseBool]
370
- func (c contextNoBodyImpl ) QueryParamBoolErr (name string ) (bool , error ) {
341
+ func (c netHttpContext [ B ] ) QueryParamBoolErr (name string ) (bool , error ) {
371
342
param := c .QueryParam (name )
372
343
if param == "" {
373
344
defaultValue , ok := c .params [name ].Default .(bool )
@@ -400,7 +371,7 @@ func (c contextNoBodyImpl) QueryParamBoolErr(name string) (bool, error) {
400
371
// )
401
372
//
402
373
// and the query parameter does not exist in the HTTP request, it will return true.
403
- func (c contextNoBodyImpl ) QueryParamBool (name string ) bool {
374
+ func (c netHttpContext [ B ] ) QueryParamBool (name string ) bool {
404
375
param , err := c .QueryParamBoolErr (name )
405
376
if err != nil {
406
377
return false
@@ -409,26 +380,26 @@ func (c contextNoBodyImpl) QueryParamBool(name string) bool {
409
380
return param
410
381
}
411
382
412
- func (c contextNoBodyImpl ) MainLang () string {
383
+ func (c netHttpContext [ B ] ) MainLang () string {
413
384
return strings .Split (c .MainLocale (), "-" )[0 ]
414
385
}
415
386
416
- func (c contextNoBodyImpl ) MainLocale () string {
387
+ func (c netHttpContext [ B ] ) MainLocale () string {
417
388
return strings .Split (c .Req .Header .Get ("Accept-Language" ), "," )[0 ]
418
389
}
419
390
420
391
// Request returns the HTTP request.
421
- func (c contextNoBodyImpl ) Request () * http.Request {
392
+ func (c netHttpContext [ B ] ) Request () * http.Request {
422
393
return c .Req
423
394
}
424
395
425
396
// Response returns the HTTP response writer.
426
- func (c contextNoBodyImpl ) Response () http.ResponseWriter {
397
+ func (c netHttpContext [ B ] ) Response () http.ResponseWriter {
427
398
return c .Res
428
399
}
429
400
430
401
// MustBody works like Body, but panics if there is an error.
431
- func (c * contextWithBodyImpl [B ]) MustBody () B {
402
+ func (c * netHttpContext [B ]) MustBody () B {
432
403
b , err := c .Body ()
433
404
if err != nil {
434
405
panic (err )
@@ -441,17 +412,17 @@ func (c *contextWithBodyImpl[B]) MustBody() B {
441
412
// It caches the result, so it can be called multiple times.
442
413
// The reason the body is cached is that it is impossible to read an HTTP request body multiple times, not because of performance.
443
414
// For decoding, it uses the Content-Type header. If it is not set, defaults to application/json.
444
- func (c * contextWithBodyImpl [B ]) Body () (B , error ) {
415
+ func (c * netHttpContext [B ]) Body () (B , error ) {
445
416
if c .body != nil {
446
417
return * c .body , nil
447
418
}
448
419
449
- body , err := body [B ](c . contextNoBodyImpl )
420
+ body , err := body [B ](* c )
450
421
c .body = & body
451
422
return body , err
452
423
}
453
424
454
- func body [B any ](c contextNoBodyImpl ) (B , error ) {
425
+ func body [B any ](c netHttpContext [ B ] ) (B , error ) {
455
426
// Limit the size of the request body.
456
427
if c .readOptions .MaxBodySize != 0 {
457
428
c .Req .Body = http .MaxBytesReader (nil , c .Req .Body , c .readOptions .MaxBodySize )
0 commit comments