func execTask(t *task) { defer func() { t.CompleteTime = time.Now().Unix() if t.Error != nil { t.ctx.Error(t.Error) t.State = types.TaskStateError } else { t.State = types.TaskStateSuccess } close(t.done) t.ctx.Debug("task completed") }() t.State = types.TaskStateRunning t.StartTime = time.Now().Unix() t.ctx.Info("executing task") if t.storRunFunc != nil && t.storService != nil { t.Result, t.Error = t.storRunFunc(t.ctx, t.storService) } else if t.runFunc != nil { t.Result, t.Error = t.runFunc(t.ctx) } else { t.Error = goof.New("invalid task") } if t.Error != nil { return } if t.Result == nil { t.ctx.Debug("skipping response schema validation; result == nil") return } if t.resultSchema == nil { t.ctx.Debug("skipping response schema validation; schema == nil") return } if !t.resultSchemaValidationEnabled { t.ctx.Debug("skipping response schema validation; disabled") return } var buf []byte if buf, t.Error = json.Marshal(t.Result); t.Error != nil { return } t.Error = schema.Validate(t.ctx, t.resultSchema, buf) if t.Error != nil { return } }
// Handle is the type's Handler function. func (h *schemaValidator) Handle( ctx types.Context, w http.ResponseWriter, req *http.Request, store types.Store) error { reqBody, err := ioutil.ReadAll(req.Body) if err != nil { return fmt.Errorf("validate req schema: read req error: %v", err) } // do the request validation if h.reqSchema != nil { err = schema.Validate(ctx, h.reqSchema, reqBody) if err != nil { return fmt.Errorf("validate req schema: validation error: %v", err) } } // create the object for the request payload if there is a function for it if h.newReqObjFunc != nil { reqObj := h.newReqObjFunc() if len(reqBody) > 0 { if err = json.Unmarshal(reqBody, reqObj); err != nil { return fmt.Errorf( "validate req schema: unmarshal error: %v", err) } } ctx = ctx.WithValue("reqObj", reqObj) } // if there's not response schema then just return the result of the next // handler if DisableResponseValidation || h.resSchema == nil { return h.handler(ctx, w, req, store) } // at this point we know there's going to be response validation, so // we need to record the result of the next handler in order to intercept // the response payload to validate it rec := httptest.NewRecorder() // invoke the next handler with a recorder err = h.handler(ctx, rec, req, store) if err != nil { return err } // do the response validation resBody := rec.Body.Bytes() err = schema.Validate(ctx, h.resSchema, resBody) if err != nil { return err } // write the recorded result of the next handler to the resposne writer w.WriteHeader(rec.Code) for k, v := range rec.HeaderMap { w.Header()[k] = v } if _, err = w.Write(resBody); err != nil { return err } return nil }