@@ -13,7 +13,6 @@ import (
1313 "strconv"
1414 "strings"
1515
16- "github.com/golang/gddo/httputil"
1716 "github.com/manyminds/api2go/jsonapi"
1817 "github.com/manyminds/api2go/routing"
1918)
@@ -182,20 +181,20 @@ func (p paginationQueryParams) getLinks(r *http.Request, count uint, info inform
182181}
183182
184183type notAllowedHandler struct {
185- marshalers map [ string ] ContentMarshaler
184+ API * API
186185}
187186
188187func (n notAllowedHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
189188 err := NewHTTPError (nil , "Method Not Allowed" , http .StatusMethodNotAllowed )
190189 w .WriteHeader (http .StatusMethodNotAllowed )
191- handleError (err , w , r , n . marshalers )
190+ n . API . handleError (err , w , r )
192191}
193192
194193type resource struct {
195194 resourceType reflect.Type
196195 source CRUD
197196 name string
198- marshalers map [ string ] ContentMarshaler
197+ api * API
199198}
200199
201200// middlewareChain executes the middleeware chain setup
@@ -210,7 +209,7 @@ func (api *API) allocateDefaultContext() APIContexter {
210209 return & APIContext {}
211210}
212211
213- func (api * API ) addResource (prototype jsonapi.MarshalIdentifier , source CRUD , marshalers map [ string ] ContentMarshaler ) * resource {
212+ func (api * API ) addResource (prototype jsonapi.MarshalIdentifier , source CRUD ) * resource {
214213 resourceType := reflect .TypeOf (prototype )
215214 if resourceType .Kind () != reflect .Struct && resourceType .Kind () != reflect .Ptr {
216215 panic ("pass an empty resource struct or a struct pointer to AddResource!" )
@@ -239,7 +238,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
239238 resourceType : resourceType ,
240239 name : name ,
241240 source : source ,
242- marshalers : marshalers ,
241+ api : api ,
243242 }
244243
245244 requestInfo := func (r * http.Request , api * API ) * information {
@@ -287,7 +286,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
287286 err := res .handleIndex (c , w , r , * info )
288287 api .contextPool .Put (c )
289288 if err != nil {
290- handleError (err , w , r , marshalers )
289+ api . handleError (err , w , r )
291290 }
292291 })
293292
@@ -299,7 +298,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
299298 err := res .handleRead (c , w , r , params , * info )
300299 api .contextPool .Put (c )
301300 if err != nil {
302- handleError (err , w , r , marshalers )
301+ api . handleError (err , w , r )
303302 }
304303 })
305304
@@ -317,7 +316,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
317316 err := res .handleReadRelation (c , w , r , params , * info , relation )
318317 api .contextPool .Put (c )
319318 if err != nil {
320- handleError (err , w , r , marshalers )
319+ api . handleError (err , w , r )
321320 }
322321 }
323322 }(relation ))
@@ -331,7 +330,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
331330 err := res .handleLinked (c , api , w , r , params , relation , * info )
332331 api .contextPool .Put (c )
333332 if err != nil {
334- handleError (err , w , r , marshalers )
333+ api . handleError (err , w , r )
335334 }
336335 }
337336 }(relation ))
@@ -344,7 +343,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
344343 err := res .handleReplaceRelation (c , w , r , params , relation )
345344 api .contextPool .Put (c )
346345 if err != nil {
347- handleError (err , w , r , marshalers )
346+ api . handleError (err , w , r )
348347 }
349348 }
350349 }(relation ))
@@ -359,7 +358,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
359358 err := res .handleAddToManyRelation (c , w , r , params , relation )
360359 api .contextPool .Put (c )
361360 if err != nil {
362- handleError (err , w , r , marshalers )
361+ api . handleError (err , w , r )
363362 }
364363 }
365364 }(relation ))
@@ -372,7 +371,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
372371 err := res .handleDeleteToManyRelation (c , w , r , params , relation )
373372 api .contextPool .Put (c )
374373 if err != nil {
375- handleError (err , w , r , marshalers )
374+ api . handleError (err , w , r )
376375 }
377376 }
378377 }(relation ))
@@ -388,7 +387,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
388387 err := res .handleCreate (c , w , r , info .prefix , * info )
389388 api .contextPool .Put (c )
390389 if err != nil {
391- handleError (err , w , r , marshalers )
390+ api . handleError (err , w , r )
392391 }
393392 })
394393
@@ -399,7 +398,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
399398 err := res .handleDelete (c , w , r , params )
400399 api .contextPool .Put (c )
401400 if err != nil {
402- handleError (err , w , r , marshalers )
401+ api . handleError (err , w , r )
403402 }
404403 })
405404
@@ -410,7 +409,7 @@ func (api *API) addResource(prototype jsonapi.MarshalIdentifier, source CRUD, ma
410409 err := res .handleUpdate (c , w , r , params )
411410 api .contextPool .Put (c )
412411 if err != nil {
413- handleError (err , w , r , marshalers )
412+ api . handleError (err , w , r )
414413 }
415414 })
416415
@@ -431,6 +430,19 @@ func buildRequest(c APIContexter, r *http.Request) Request {
431430 return req
432431}
433432
433+ func (res * resource ) marshalResponse (resp interface {}, w http.ResponseWriter , status int , r * http.Request ) error {
434+ filtered , err := filterSparseFields (resp , r )
435+ if err != nil {
436+ return err
437+ }
438+ result , err := json .Marshal (filtered )
439+ if err != nil {
440+ return err
441+ }
442+ writeResult (w , result , status , res .api .ContentType )
443+ return nil
444+ }
445+
434446func (res * resource ) handleIndex (c APIContexter , w http.ResponseWriter , r * http.Request , info information ) error {
435447 pagination := newPaginationQueryParams (r )
436448 if pagination .isValid () {
@@ -449,7 +461,7 @@ func (res *resource) handleIndex(c APIContexter, w http.ResponseWriter, r *http.
449461 return err
450462 }
451463
452- return respondWithPagination (response , info , http .StatusOK , paginationLinks , w , r , res . marshalers )
464+ return res . respondWithPagination (response , info , http .StatusOK , paginationLinks , w , r )
453465 }
454466 source , ok := res .source .(FindAll )
455467 if ! ok {
@@ -461,7 +473,7 @@ func (res *resource) handleIndex(c APIContexter, w http.ResponseWriter, r *http.
461473 return err
462474 }
463475
464- return respondWith (response , info , http .StatusOK , w , r , res . marshalers )
476+ return res . respondWith (response , info , http .StatusOK , w , r )
465477}
466478
467479func (res * resource ) handleRead (c APIContexter , w http.ResponseWriter , r * http.Request , params map [string ]string , info information ) error {
@@ -473,7 +485,7 @@ func (res *resource) handleRead(c APIContexter, w http.ResponseWriter, r *http.R
473485 return err
474486 }
475487
476- return respondWith (response , info , http .StatusOK , w , r , res . marshalers )
488+ return res . respondWith (response , info , http .StatusOK , w , r )
477489}
478490
479491func (res * resource ) handleReadRelation (c APIContexter , w http.ResponseWriter , r * http.Request , params map [string ]string , info information , relation jsonapi.Reference ) error {
@@ -499,7 +511,7 @@ func (res *resource) handleReadRelation(c APIContexter, w http.ResponseWriter, r
499511 rel .Meta = meta
500512 }
501513
502- return marshalResponse (rel , w , http .StatusOK , r , res . marshalers )
514+ return res . marshalResponse (rel , w , http .StatusOK , r )
503515}
504516
505517// try to find the referenced resource and call the findAll Method with referencing resource id as param
@@ -530,7 +542,7 @@ func (res *resource) handleLinked(c APIContexter, api *API, w http.ResponseWrite
530542 return err
531543 }
532544
533- return respondWithPagination (response , info , http .StatusOK , paginationLinks , w , r , res . marshalers )
545+ return res . respondWithPagination (response , info , http .StatusOK , paginationLinks , w , r )
534546 }
535547
536548 source , ok := resource .source .(FindAll )
@@ -542,7 +554,7 @@ func (res *resource) handleLinked(c APIContexter, api *API, w http.ResponseWrite
542554 if err != nil {
543555 return err
544556 }
545- return respondWith (obj , info , http .StatusOK , w , r , res . marshalers )
557+ return res . respondWith (obj , info , http .StatusOK , w , r )
546558 }
547559 }
548560
@@ -554,7 +566,7 @@ func (res *resource) handleLinked(c APIContexter, api *API, w http.ResponseWrite
554566}
555567
556568func (res * resource ) handleCreate (c APIContexter , w http.ResponseWriter , r * http.Request , prefix string , info information ) error {
557- ctx , err := unmarshalRequest (r , res . marshalers )
569+ ctx , err := unmarshalRequest (r )
558570 if err != nil {
559571 return err
560572 }
@@ -595,7 +607,7 @@ func (res *resource) handleCreate(c APIContexter, w http.ResponseWriter, r *http
595607 // handle 200 status codes
596608 switch response .StatusCode () {
597609 case http .StatusCreated :
598- return respondWith (response , info , http .StatusCreated , w , r , res . marshalers )
610+ return res . respondWith (response , info , http .StatusCreated , w , r )
599611 case http .StatusNoContent :
600612 w .WriteHeader (response .StatusCode ())
601613 return nil
@@ -614,7 +626,7 @@ func (res *resource) handleUpdate(c APIContexter, w http.ResponseWriter, r *http
614626 return err
615627 }
616628
617- ctx , err := unmarshalRequest (r , res . marshalers )
629+ ctx , err := unmarshalRequest (r )
618630 if err != nil {
619631 return err
620632 }
@@ -655,7 +667,7 @@ func (res *resource) handleUpdate(c APIContexter, w http.ResponseWriter, r *http
655667 response = internalResponse
656668 }
657669
658- return respondWith (response , information {}, http .StatusOK , w , r , res . marshalers )
670+ return res . respondWith (response , information {}, http .StatusOK , w , r )
659671 case http .StatusAccepted :
660672 w .WriteHeader (http .StatusAccepted )
661673 return nil
@@ -680,7 +692,7 @@ func (res *resource) handleReplaceRelation(c APIContexter, w http.ResponseWriter
680692 return err
681693 }
682694
683- body , err := unmarshalRequest (r , res . marshalers )
695+ body , err := unmarshalRequest (r )
684696 if err != nil {
685697 return err
686698 }
@@ -730,7 +742,7 @@ func (res *resource) handleAddToManyRelation(c APIContexter, w http.ResponseWrit
730742 return err
731743 }
732744
733- body , err := unmarshalRequest (r , res . marshalers )
745+ body , err := unmarshalRequest (r )
734746 if err != nil {
735747 return err
736748 }
@@ -802,7 +814,7 @@ func (res *resource) handleDeleteToManyRelation(c APIContexter, w http.ResponseW
802814 return err
803815 }
804816
805- body , err := unmarshalRequest (r , res . marshalers )
817+ body , err := unmarshalRequest (r )
806818 if err != nil {
807819 return err
808820 }
@@ -883,7 +895,7 @@ func (res *resource) handleDelete(c APIContexter, w http.ResponseWriter, r *http
883895 "meta" : response .Metadata (),
884896 }
885897
886- return marshalResponse (data , w , http .StatusOK , r , res . marshalers )
898+ return res . marshalResponse (data , w , http .StatusOK , r )
887899 case http .StatusAccepted :
888900 w .WriteHeader (http .StatusAccepted )
889901 return nil
@@ -901,7 +913,7 @@ func writeResult(w http.ResponseWriter, data []byte, status int, contentType str
901913 w .Write (data )
902914}
903915
904- func respondWith (obj Responder , info information , status int , w http.ResponseWriter , r * http.Request , marshalers map [ string ] ContentMarshaler ) error {
916+ func ( res * resource ) respondWith (obj Responder , info information , status int , w http.ResponseWriter , r * http.Request ) error {
905917 data , err := jsonapi .MarshalToStruct (obj .Result (), info )
906918 if err != nil {
907919 return err
@@ -912,10 +924,10 @@ func respondWith(obj Responder, info information, status int, w http.ResponseWri
912924 data .Meta = meta
913925 }
914926
915- return marshalResponse (data , w , status , r , marshalers )
927+ return res . marshalResponse (data , w , status , r )
916928}
917929
918- func respondWithPagination (obj Responder , info information , status int , links jsonapi.Links , w http.ResponseWriter , r * http.Request , marshalers map [ string ] ContentMarshaler ) error {
930+ func ( res * resource ) respondWithPagination (obj Responder , info information , status int , links jsonapi.Links , w http.ResponseWriter , r * http.Request ) error {
919931 data , err := jsonapi .MarshalToStruct (obj .Result (), info )
920932 if err != nil {
921933 return err
@@ -927,39 +939,18 @@ func respondWithPagination(obj Responder, info information, status int, links js
927939 data .Meta = meta
928940 }
929941
930- return marshalResponse (data , w , status , r , marshalers )
942+ return res . marshalResponse (data , w , status , r )
931943}
932944
933- func unmarshalRequest (r * http.Request , marshalers map [ string ] ContentMarshaler ) ([]byte , error ) {
945+ func unmarshalRequest (r * http.Request ) ([]byte , error ) {
934946 defer r .Body .Close ()
935947 data , err := ioutil .ReadAll (r .Body )
936948 if err != nil {
937949 return nil , err
938950 }
939- // Todo: custom content unmarshaler is broken atm
940- //result := map[string]interface{}{}
941- //marshaler, _ := selectContentMarshaler(r, marshalers)
942- //err = marshaler.Unmarshal(data, &result)
943- //if err != nil {
944- //return nil, err
945- //}
946951 return data , nil
947952}
948953
949- func marshalResponse (resp interface {}, w http.ResponseWriter , status int , r * http.Request , marshalers map [string ]ContentMarshaler ) error {
950- marshaler , contentType := selectContentMarshaler (r , marshalers )
951- filtered , err := filterSparseFields (resp , r )
952- if err != nil {
953- return err
954- }
955- result , err := marshaler .Marshal (filtered )
956- if err != nil {
957- return err
958- }
959- writeResult (w , result , status , contentType )
960- return nil
961- }
962-
963954func filterSparseFields (resp interface {}, r * http.Request ) (interface {}, error ) {
964955 query := r .URL .Query ()
965956 queryParams := parseQueryFields (& query )
@@ -1067,39 +1058,16 @@ func replaceAttributes(query *map[string][]string, entry *jsonapi.Data) map[stri
10671058 return nil
10681059}
10691060
1070- func selectContentMarshaler (r * http.Request , marshalers map [string ]ContentMarshaler ) (marshaler ContentMarshaler , contentType string ) {
1071- if _ , found := r .Header ["Accept" ]; found {
1072- var contentTypes []string
1073- for ct := range marshalers {
1074- contentTypes = append (contentTypes , ct )
1075- }
1076-
1077- contentType = httputil .NegotiateContentType (r , contentTypes , defaultContentTypHeader )
1078- marshaler = marshalers [contentType ]
1079- } else if contentTypes , found := r .Header ["Content-Type" ]; found {
1080- contentType = contentTypes [0 ]
1081- marshaler = marshalers [contentType ]
1082- }
1083-
1084- if marshaler == nil {
1085- contentType = defaultContentTypHeader
1086- marshaler = JSONContentMarshaler {}
1087- }
1088-
1089- return
1090- }
1091-
1092- func handleError (err error , w http.ResponseWriter , r * http.Request , marshalers map [string ]ContentMarshaler ) {
1093- marshaler , contentType := selectContentMarshaler (r , marshalers )
1094-
1061+ func (api * API ) handleError (err error , w http.ResponseWriter , r * http.Request ) {
10951062 log .Println (err )
10961063 if e , ok := err .(HTTPError ); ok {
1097- writeResult (w , []byte (marshaler . MarshalError ( err )), e .status , contentType )
1064+ writeResult (w , []byte (marshalHTTPError ( e )), e .status , api . ContentType )
10981065 return
10991066
11001067 }
11011068
1102- writeResult (w , []byte (marshaler .MarshalError (err )), http .StatusInternalServerError , contentType )
1069+ e := NewHTTPError (err , err .Error (), http .StatusInternalServerError )
1070+ writeResult (w , []byte (marshalHTTPError (e )), http .StatusInternalServerError , api .ContentType )
11031071}
11041072
11051073// TODO: this can also be replaced with a struct into that we directly json.Unmarshal
0 commit comments