In the platform adapter, we ask the URM for a list of tasks the user
owns, and then we look up each task individually.
The task service tests uncovered a legitimate bug where FindTasks would
return a "task not found" error, originating from looking up a task that
was present when we interrogated the URM but was deleted before we could
find it in the task store.
This change also removes duplicated URM logic from the HTTP handler
which has since been pushed down into the platform adapter.
This can be done by embedding a httprouter.Router
(a light weight HTTP router that supports variables in the routing pattern and matches against the request method)
Required services should be exported on the struct
// ThingHandler represents an HTTP API handler for things.
typeThingHandlerstruct{// embedded httprouter.Router as a lazy way to implement http.Handler
*httprouter.RouterThingServiceplatform.ThingServiceAuthorizationServiceplatform.AuthorizationServiceLogger*zap.Logger}
HTTP Handler Constructor
Routes should be declared in the constructor
// NewThingHandler returns a new instance of ThingHandler.
funcNewThingHandler()*ThingHandler{h:=&ThingHandler{Router:httprouter.New(),Logger:zap.Nop(),}h.HandlerFunc("POST","/api/v2/things",h.handlePostThing)h.HandlerFunc("GET","/api/v2/things",h.handleGetThings)returnh}
Route handlers (http.HandlerFuncs)
Each route handler should have an associated request struct and decode function
The decode function should take a context.Context and an *http.Request and return the associated route request struct
Route http.HandlerFuncs should separate the decoding and encoding of HTTP requests/response from actual handler logic
// handlePostThing is the HTTP handler for the POST /api/v2/things route.
func(h*ThingHandler)handlePostThing(whttp.ResponseWriter,r*http.Request){ctx:=r.Context()req,err:=decodePostThingRequest(ctx,r)iferr!=nil{errors.EncodeHTTP(ctx,err,w)return}// Do stuff here
iferr:=h.ThingService.CreateThing(ctx,req.Thing);err!=nil{errors.EncodeHTTP(ctx,err,w)return}iferr:=encodeResponse(ctx,w,http.StatusCreated,req.Thing);err!=nil{h.Logger.Info("encoding response failed",zap.Error(err))return}}
http.HandlerFunc's that require particular encoding of http responses should implement an encode response function