// NewCreateBottleContext parses the incoming request URL and body, performs validations and creates the // context used by the bottle controller create action. func NewCreateBottleContext(ctx context.Context, service *goa.Service) (*CreateBottleContext, error) { var err error resp := goa.ContextResponse(ctx) resp.Service = service req := goa.ContextRequest(ctx) rctx := CreateBottleContext{Context: ctx, ResponseData: resp, RequestData: req} return &rctx, err }
// LogRequest creates a request logger middleware. // This middleware is aware of the RequestID middleware and if registered after it leverages the // request ID for logging. // If verbose is true then the middlware logs the request and response bodies. func LogRequest(verbose bool) goa.Middleware { return func(h goa.Handler) goa.Handler { return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { reqID := ctx.Value(reqIDKey) if reqID == nil { reqID = shortID() } ctx = goa.WithLogContext(ctx, "req_id", reqID) startedAt := time.Now() r := goa.ContextRequest(ctx) goa.LogInfo(ctx, "started", r.Method, r.URL.String(), "from", from(req), "ctrl", goa.ContextController(ctx), "action", goa.ContextAction(ctx)) if verbose { if len(r.Params) > 0 { logCtx := make([]interface{}, 2*len(r.Params)) i := 0 for k, v := range r.Params { logCtx[i] = k logCtx[i+1] = interface{}(strings.Join(v, ", ")) i = i + 2 } goa.LogInfo(ctx, "params", logCtx...) } if r.ContentLength > 0 { if mp, ok := r.Payload.(map[string]interface{}); ok { logCtx := make([]interface{}, 2*len(mp)) i := 0 for k, v := range mp { logCtx[i] = k logCtx[i+1] = interface{}(v) i = i + 2 } goa.LogInfo(ctx, "payload", logCtx...) } else { // Not the most efficient but this is used for debugging js, err := json.Marshal(r.Payload) if err != nil { js = []byte("<invalid JSON>") } goa.LogInfo(ctx, "payload", "raw", string(js)) } } } err := h(ctx, rw, req) resp := goa.ContextResponse(ctx) if code := resp.ErrorCode; code != "" { goa.LogInfo(ctx, "completed", "status", resp.Status, "error", code, "bytes", resp.Length, "time", time.Since(startedAt).String()) } else { goa.LogInfo(ctx, "completed", "status", resp.Status, "bytes", resp.Length, "time", time.Since(startedAt).String()) } return err } } }
// unmarshalCreateBottlePayload unmarshals the request body into the context request data Payload field. func unmarshalCreateBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error { payload := &createBottlePayload{} if err := service.DecodeRequest(req, payload); err != nil { return err } if err := payload.Validate(); err != nil { return err } goa.ContextRequest(ctx).Payload = payload.Publicize() return nil }
// NewShowBottleContext parses the incoming request URL and body, performs validations and creates the // context used by the bottle controller show action. func NewShowBottleContext(ctx context.Context, service *goa.Service) (*ShowBottleContext, error) { var err error resp := goa.ContextResponse(ctx) resp.Service = service req := goa.ContextRequest(ctx) rctx := ShowBottleContext{Context: ctx, ResponseData: resp, RequestData: req} paramID := req.Params["id"] if len(paramID) > 0 { rawID := paramID[0] if id, err2 := strconv.Atoi(rawID); err2 == nil { rctx.ID = id } else { err = goa.MergeErrors(err, goa.InvalidParamTypeError("id", rawID, "integer")) } } return &rctx, err }
// MountBottleController "mounts" a Bottle resource controller on the given service. func MountBottleController(service *goa.Service, ctrl BottleController) { initService(service) var h goa.Handler h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { // Check if there was an error loading the request if err := goa.ContextError(ctx); err != nil { return err } // Build the context rctx, err := NewCreateBottleContext(ctx, service) if err != nil { return err } // Build the payload if rawPayload := goa.ContextRequest(ctx).Payload; rawPayload != nil { rctx.Payload = rawPayload.(*CreateBottlePayload) } else { return goa.MissingPayloadError() } return ctrl.Create(rctx) } service.Mux.Handle("POST", "/bottles", ctrl.MuxHandler("Create", h, unmarshalCreateBottlePayload)) service.LogInfo("mount", "ctrl", "Bottle", "action", "Create", "route", "POST /bottles") h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { // Check if there was an error loading the request if err := goa.ContextError(ctx); err != nil { return err } // Build the context rctx, err := NewShowBottleContext(ctx, service) if err != nil { return err } return ctrl.Show(rctx) } service.Mux.Handle("GET", "/bottles/:id", ctrl.MuxHandler("Show", h, nil)) service.LogInfo("mount", "ctrl", "Bottle", "action", "Show", "route", "GET /bottles/:id") }
var _ = Describe("Gzip", func() { var ctx context.Context var req *http.Request var rw *TestResponseWriter payload := map[string]interface{}{"payload": 42} BeforeEach(func() { var err error req, err = http.NewRequest("POST", "/foo/bar", strings.NewReader(`{"payload":42}`)) req.Header.Set("Accept-Encoding", "gzip") Ω(err).ShouldNot(HaveOccurred()) rw = &TestResponseWriter{ParentHeader: make(http.Header)} ctx = goa.NewContext(nil, rw, req, nil) goa.ContextRequest(ctx).Payload = payload }) It("encodes response using gzip", func() { h := func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { resp := goa.ContextResponse(ctx) resp.Write([]byte("gzip me!")) resp.WriteHeader(http.StatusOK) return nil } t := gzm.Middleware(gzip.BestCompression)(h) err := t(ctx, rw, req) Ω(err).ShouldNot(HaveOccurred()) resp := goa.ContextResponse(ctx) Ω(resp.Status).Should(Equal(http.StatusOK))
}) BeforeEach(func() { handler = func(c context.Context, rw http.ResponseWriter, req *http.Request) error { ctx = c rw.WriteHeader(respStatus) rw.Write(respContent) return nil } unmarshaler = func(c context.Context, service *goa.Service, req *http.Request) error { ctx = c if req != nil { var payload interface{} err := service.DecodeRequest(req, &payload) Ω(err).ShouldNot(HaveOccurred()) goa.ContextRequest(ctx).Payload = payload } return nil } }) It("creates a handle", func() { Ω(muxHandler).ShouldNot(BeNil()) }) Context("with a request", func() { var rw http.ResponseWriter var r *http.Request var p url.Values BeforeEach(func() {