@@ -191,6 +191,18 @@ type resource struct {
191191 marshalers map [string ]ContentMarshaler
192192}
193193
194+ // middlewareChain executes the middleeware chain setup
195+ func (api * API ) middlewareChain (c APIContexter , w http.ResponseWriter , r * http.Request ) {
196+ for _ , middleware := range api .middlewares {
197+ middleware (c , w , r )
198+ }
199+ }
200+
201+ // allocateContext creates a context for the api.contextPool, saving allocations
202+ func (api * API ) allocateDefaultContext () APIContexter {
203+ return & APIContext {}
204+ }
205+
194206func (api * API ) addResource (prototype jsonapi.MarshalIdentifier , source CRUD , marshalers map [string ]ContentMarshaler ) * resource {
195207 resourceType := reflect .TypeOf (prototype )
196208 if resourceType .Kind () != reflect .Struct && resourceType .Kind () != reflect .Ptr {
@@ -224,24 +236,40 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
224236 }
225237
226238 api .router .Handle ("OPTIONS" , api .prefix + name , func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
239+ c := api .contextPool .Get ().(APIContexter )
240+ c .Reset ()
241+ api .middlewareChain (c , w , r )
227242 w .Header ().Set ("Allow" , "GET,POST,PATCH,OPTIONS" )
228243 w .WriteHeader (http .StatusNoContent )
244+ api .contextPool .Put (c )
229245 })
230246
231247 api .router .Handle ("OPTIONS" , api .prefix + name + "/:id" , func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
248+ c := api .contextPool .Get ().(APIContexter )
249+ c .Reset ()
250+ api .middlewareChain (c , w , r )
232251 w .Header ().Set ("Allow" , "GET,PATCH,DELETE,OPTIONS" )
233252 w .WriteHeader (http .StatusNoContent )
253+ api .contextPool .Put (c )
234254 })
235255
236256 api .router .GET (api .prefix + name , func (w http.ResponseWriter , r * http.Request , _ httprouter.Params ) {
237- err := res .handleIndex (w , r , api .info )
257+ c := api .contextPool .Get ().(APIContexter )
258+ c .Reset ()
259+ api .middlewareChain (c , w , r )
260+ err := res .handleIndex (c , w , r , api .info )
261+ api .contextPool .Put (c )
238262 if err != nil {
239263 handleError (err , w , r , marshalers )
240264 }
241265 })
242266
243267 api .router .GET (api .prefix + name + "/:id" , func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
244- err := res .handleRead (w , r , ps , api .info )
268+ c := api .contextPool .Get ().(APIContexter )
269+ c .Reset ()
270+ api .middlewareChain (c , w , r )
271+ err := res .handleRead (c , w , r , ps , api .info )
272+ api .contextPool .Put (c )
245273 if err != nil {
246274 handleError (err , w , r , marshalers )
247275 }
@@ -254,7 +282,11 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
254282 for _ , relation := range relations {
255283 api .router .GET (api .prefix + name + "/:id/relationships/" + relation .Name , func (relation jsonapi.Reference ) httprouter.Handle {
256284 return func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
257- err := res .handleReadRelation (w , r , ps , api .info , relation )
285+ c := api .contextPool .Get ().(APIContexter )
286+ c .Reset ()
287+ api .middlewareChain (c , w , r )
288+ err := res .handleReadRelation (c , w , r , ps , api .info , relation )
289+ api .contextPool .Put (c )
258290 if err != nil {
259291 handleError (err , w , r , marshalers )
260292 }
@@ -263,7 +295,11 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
263295
264296 api .router .GET (api .prefix + name + "/:id/" + relation .Name , func (relation jsonapi.Reference ) httprouter.Handle {
265297 return func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
266- err := res .handleLinked (api , w , r , ps , relation , api .info )
298+ c := api .contextPool .Get ().(APIContexter )
299+ c .Reset ()
300+ api .middlewareChain (c , w , r )
301+ err := res .handleLinked (c , api , w , r , ps , relation , api .info )
302+ api .contextPool .Put (c )
267303 if err != nil {
268304 handleError (err , w , r , marshalers )
269305 }
@@ -272,7 +308,11 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
272308
273309 api .router .PATCH (api .prefix + name + "/:id/relationships/" + relation .Name , func (relation jsonapi.Reference ) httprouter.Handle {
274310 return func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
275- err := res .handleReplaceRelation (w , r , ps , relation )
311+ c := api .contextPool .Get ().(APIContexter )
312+ c .Reset ()
313+ api .middlewareChain (c , w , r )
314+ err := res .handleReplaceRelation (c , w , r , ps , relation )
315+ api .contextPool .Put (c )
276316 if err != nil {
277317 handleError (err , w , r , marshalers )
278318 }
@@ -283,7 +323,11 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
283323 // generate additional routes to manipulate to-many relationships
284324 api .router .POST (api .prefix + name + "/:id/relationships/" + relation .Name , func (relation jsonapi.Reference ) httprouter.Handle {
285325 return func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
286- err := res .handleAddToManyRelation (w , r , ps , relation )
326+ c := api .contextPool .Get ().(APIContexter )
327+ c .Reset ()
328+ api .middlewareChain (c , w , r )
329+ err := res .handleAddToManyRelation (c , w , r , ps , relation )
330+ api .contextPool .Put (c )
287331 if err != nil {
288332 handleError (err , w , r , marshalers )
289333 }
@@ -292,7 +336,11 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
292336
293337 api .router .DELETE (api .prefix + name + "/:id/relationships/" + relation .Name , func (relation jsonapi.Reference ) httprouter.Handle {
294338 return func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
295- err := res .handleDeleteToManyRelation (w , r , ps , relation )
339+ c := api .contextPool .Get ().(APIContexter )
340+ c .Reset ()
341+ api .middlewareChain (c , w , r )
342+ err := res .handleDeleteToManyRelation (c , w , r , ps , relation )
343+ api .contextPool .Put (c )
296344 if err != nil {
297345 handleError (err , w , r , marshalers )
298346 }
@@ -303,21 +351,33 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
303351 }
304352
305353 api .router .POST (api .prefix + name , func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
306- err := res .handleCreate (w , r , api .prefix , api .info )
354+ c := api .contextPool .Get ().(APIContexter )
355+ c .Reset ()
356+ api .middlewareChain (c , w , r )
357+ err := res .handleCreate (c , w , r , api .prefix , api .info )
358+ api .contextPool .Put (c )
307359 if err != nil {
308360 handleError (err , w , r , marshalers )
309361 }
310362 })
311363
312364 api .router .DELETE (api .prefix + name + "/:id" , func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
313- err := res .handleDelete (w , r , ps )
365+ c := api .contextPool .Get ().(APIContexter )
366+ c .Reset ()
367+ api .middlewareChain (c , w , r )
368+ err := res .handleDelete (c , w , r , ps )
369+ api .contextPool .Put (c )
314370 if err != nil {
315371 handleError (err , w , r , marshalers )
316372 }
317373 })
318374
319375 api .router .PATCH (api .prefix + name + "/:id" , func (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) {
320- err := res .handleUpdate (w , r , ps )
376+ c := api .contextPool .Get ().(APIContexter )
377+ c .Reset ()
378+ api .middlewareChain (c , w , r )
379+ err := res .handleUpdate (c , w , r , ps )
380+ api .contextPool .Put (c )
321381 if err != nil {
322382 handleError (err , w , r , marshalers )
323383 }
@@ -328,26 +388,27 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
328388 return & res
329389}
330390
331- func buildRequest (r * http.Request ) Request {
391+ func buildRequest (c APIContexter , r * http.Request ) Request {
332392 req := Request {PlainRequest : r }
333393 params := make (map [string ][]string )
334394 for key , values := range r .URL .Query () {
335395 params [key ] = strings .Split (values [0 ], "," )
336396 }
337397 req .QueryParams = params
338398 req .Header = r .Header
399+ req .Context = c
339400 return req
340401}
341402
342- func (res * resource ) handleIndex (w http.ResponseWriter , r * http.Request , info information ) error {
403+ func (res * resource ) handleIndex (c APIContexter , w http.ResponseWriter , r * http.Request , info information ) error {
343404 pagination := newPaginationQueryParams (r )
344405 if pagination .isValid () {
345406 source , ok := res .source .(PaginatedFindAll )
346407 if ! ok {
347408 return NewHTTPError (nil , "Resource does not implement the PaginatedFindAll interface" , http .StatusNotFound )
348409 }
349410
350- count , response , err := source .PaginatedFindAll (buildRequest (r ))
411+ count , response , err := source .PaginatedFindAll (buildRequest (c , r ))
351412 if err != nil {
352413 return err
353414 }
@@ -364,18 +425,18 @@ func (res *resource) handleIndex(w http.ResponseWriter, r *http.Request, info in
364425 return NewHTTPError (nil , "Resource does not implement the FindAll interface" , http .StatusNotFound )
365426 }
366427
367- response , err := source .FindAll (buildRequest (r ))
428+ response , err := source .FindAll (buildRequest (c , r ))
368429 if err != nil {
369430 return err
370431 }
371432
372433 return respondWith (response , info , http .StatusOK , w , r , res .marshalers )
373434}
374435
375- func (res * resource ) handleRead (w http.ResponseWriter , r * http.Request , ps httprouter.Params , info information ) error {
436+ func (res * resource ) handleRead (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params , info information ) error {
376437 id := ps .ByName ("id" )
377438
378- response , err := res .source .FindOne (id , buildRequest (r ))
439+ response , err := res .source .FindOne (id , buildRequest (c , r ))
379440
380441 if err != nil {
381442 return err
@@ -384,10 +445,10 @@ func (res *resource) handleRead(w http.ResponseWriter, r *http.Request, ps httpr
384445 return respondWith (response , info , http .StatusOK , w , r , res .marshalers )
385446}
386447
387- func (res * resource ) handleReadRelation (w http.ResponseWriter , r * http.Request , ps httprouter.Params , info information , relation jsonapi.Reference ) error {
448+ func (res * resource ) handleReadRelation (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params , info information , relation jsonapi.Reference ) error {
388449 id := ps .ByName ("id" )
389450
390- obj , err := res .source .FindOne (id , buildRequest (r ))
451+ obj , err := res .source .FindOne (id , buildRequest (c , r ))
391452 if err != nil {
392453 return err
393454 }
@@ -440,11 +501,11 @@ func (res *resource) handleReadRelation(w http.ResponseWriter, r *http.Request,
440501}
441502
442503// try to find the referenced resource and call the findAll Method with referencing resource id as param
443- func (res * resource ) handleLinked (api * API , w http.ResponseWriter , r * http.Request , ps httprouter.Params , linked jsonapi.Reference , info information ) error {
504+ func (res * resource ) handleLinked (c APIContexter , api * API , w http.ResponseWriter , r * http.Request , ps httprouter.Params , linked jsonapi.Reference , info information ) error {
444505 id := ps .ByName ("id" )
445506 for _ , resource := range api .resources {
446507 if resource .name == linked .Type {
447- request := buildRequest (r )
508+ request := buildRequest (c , r )
448509 request .QueryParams [res .name + "ID" ] = []string {id }
449510 request .QueryParams [res .name + "Name" ] = []string {linked .Name }
450511
@@ -495,7 +556,7 @@ func (res *resource) handleLinked(api *API, w http.ResponseWriter, r *http.Reque
495556
496557}
497558
498- func (res * resource ) handleCreate (w http.ResponseWriter , r * http.Request , prefix string , info information ) error {
559+ func (res * resource ) handleCreate (c APIContexter , w http.ResponseWriter , r * http.Request , prefix string , info information ) error {
499560 ctx , err := unmarshalRequest (r , res .marshalers )
500561 if err != nil {
501562 return err
@@ -518,7 +579,7 @@ func (res *resource) handleCreate(w http.ResponseWriter, r *http.Request, prefix
518579 //TODO create multiple objects not only one.
519580 newObj := newObjs .Index (0 ).Interface ()
520581
521- response , err := res .source .Create (newObj , buildRequest (r ))
582+ response , err := res .source .Create (newObj , buildRequest (c , r ))
522583 if err != nil {
523584 return err
524585 }
@@ -545,8 +606,8 @@ func (res *resource) handleCreate(w http.ResponseWriter, r *http.Request, prefix
545606 }
546607}
547608
548- func (res * resource ) handleUpdate (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) error {
549- obj , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (r ))
609+ func (res * resource ) handleUpdate (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params ) error {
610+ obj , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (c , r ))
550611 if err != nil {
551612 return err
552613 }
@@ -609,7 +670,7 @@ func (res *resource) handleUpdate(w http.ResponseWriter, r *http.Request, ps htt
609670
610671 updatingObj := updatingObjs .Index (0 ).Interface ()
611672
612- response , err := res .source .Update (updatingObj , buildRequest (r ))
673+ response , err := res .source .Update (updatingObj , buildRequest (c , r ))
613674
614675 if err != nil {
615676 return err
@@ -619,7 +680,7 @@ func (res *resource) handleUpdate(w http.ResponseWriter, r *http.Request, ps htt
619680 case http .StatusOK :
620681 updated := response .Result ()
621682 if updated == nil {
622- internalResponse , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (r ))
683+ internalResponse , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (c , r ))
623684 if err != nil {
624685 return err
625686 }
@@ -643,13 +704,13 @@ func (res *resource) handleUpdate(w http.ResponseWriter, r *http.Request, ps htt
643704 }
644705}
645706
646- func (res * resource ) handleReplaceRelation (w http.ResponseWriter , r * http.Request , ps httprouter.Params , relation jsonapi.Reference ) error {
707+ func (res * resource ) handleReplaceRelation (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params , relation jsonapi.Reference ) error {
647708 var (
648709 err error
649710 editObj interface {}
650711 )
651712
652- response , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (r ))
713+ response , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (c , r ))
653714 if err != nil {
654715 return err
655716 }
@@ -677,22 +738,22 @@ func (res *resource) handleReplaceRelation(w http.ResponseWriter, r *http.Reques
677738 }
678739
679740 if resType == reflect .Struct {
680- _ , err = res .source .Update (reflect .ValueOf (editObj ).Elem ().Interface (), buildRequest (r ))
741+ _ , err = res .source .Update (reflect .ValueOf (editObj ).Elem ().Interface (), buildRequest (c , r ))
681742 } else {
682- _ , err = res .source .Update (editObj , buildRequest (r ))
743+ _ , err = res .source .Update (editObj , buildRequest (c , r ))
683744 }
684745
685746 w .WriteHeader (http .StatusNoContent )
686747 return err
687748}
688749
689- func (res * resource ) handleAddToManyRelation (w http.ResponseWriter , r * http.Request , ps httprouter.Params , relation jsonapi.Reference ) error {
750+ func (res * resource ) handleAddToManyRelation (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params , relation jsonapi.Reference ) error {
690751 var (
691752 err error
692753 editObj interface {}
693754 )
694755
695- response , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (r ))
756+ response , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (c , r ))
696757 if err != nil {
697758 return err
698759 }
@@ -741,22 +802,22 @@ func (res *resource) handleAddToManyRelation(w http.ResponseWriter, r *http.Requ
741802 targetObj .AddToManyIDs (relation .Name , newIDs )
742803
743804 if resType == reflect .Struct {
744- _ , err = res .source .Update (reflect .ValueOf (targetObj ).Elem ().Interface (), buildRequest (r ))
805+ _ , err = res .source .Update (reflect .ValueOf (targetObj ).Elem ().Interface (), buildRequest (c , r ))
745806 } else {
746- _ , err = res .source .Update (targetObj , buildRequest (r ))
807+ _ , err = res .source .Update (targetObj , buildRequest (c , r ))
747808 }
748809
749810 w .WriteHeader (http .StatusNoContent )
750811
751812 return err
752813}
753814
754- func (res * resource ) handleDeleteToManyRelation (w http.ResponseWriter , r * http.Request , ps httprouter.Params , relation jsonapi.Reference ) error {
815+ func (res * resource ) handleDeleteToManyRelation (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params , relation jsonapi.Reference ) error {
755816 var (
756817 err error
757818 editObj interface {}
758819 )
759- response , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (r ))
820+ response , err := res .source .FindOne (ps .ByName ("id" ), buildRequest (c , r ))
760821 if err != nil {
761822 return err
762823 }
@@ -805,9 +866,9 @@ func (res *resource) handleDeleteToManyRelation(w http.ResponseWriter, r *http.R
805866 targetObj .DeleteToManyIDs (relation .Name , obsoleteIDs )
806867
807868 if resType == reflect .Struct {
808- _ , err = res .source .Update (reflect .ValueOf (targetObj ).Elem ().Interface (), buildRequest (r ))
869+ _ , err = res .source .Update (reflect .ValueOf (targetObj ).Elem ().Interface (), buildRequest (c , r ))
809870 } else {
810- _ , err = res .source .Update (targetObj , buildRequest (r ))
871+ _ , err = res .source .Update (targetObj , buildRequest (c , r ))
811872 }
812873
813874 w .WriteHeader (http .StatusNoContent )
@@ -823,8 +884,8 @@ func getPointerToStruct(oldObj interface{}) interface{} {
823884 return ptr .Interface ()
824885}
825886
826- func (res * resource ) handleDelete (w http.ResponseWriter , r * http.Request , ps httprouter.Params ) error {
827- response , err := res .source .Delete (ps .ByName ("id" ), buildRequest (r ))
887+ func (res * resource ) handleDelete (c APIContexter , w http.ResponseWriter , r * http.Request , ps httprouter.Params ) error {
888+ response , err := res .source .Delete (ps .ByName ("id" ), buildRequest (c , r ))
828889 if err != nil {
829890 return err
830891 }
0 commit comments