func SerializeResponseMiddleware(registry kit.Registry, request kit.Request, response kit.Response) (kit.Response, bool) { // Try to serialize the reponse data. // Determine serializer. serializer := registry.DefaultSerializer() // Check if a custom serializer was specified. if name := request.GetContext().String("response-serializer"); name != "" { serializer = registry.Serializer(name) if serializer == nil { errResp := kit.NewErrorResponse("unknown_response_serializer", true) data, _ := serializer.MustSerializeResponse(errResp) errResp.SetData(data) return errResp, false } } // Set format in metadata. meta := response.GetMeta() if meta == nil { meta = make(map[string]interface{}) } meta["format"] = serializer.Name() response.SetMeta(meta) data, err := serializer.MustSerializeResponse(response) if err != nil { registry.Logger().Errorf("Response serialization error: %v (%+v)", err, response) } response.SetData(data) return nil, false }
func (PageResource) ApiAlterQuery(res kit.Resource, query db.Query, r kit.Request) apperror.Error { typ := r.GetContext().String("type") if typ != "" { query.Filter("type", typ) } return nil }
func HandleFind(registry kit.Registry, request kit.Request) (kit.Response, bool) { collection := request.GetContext().MustString("collection") res := registry.Resource(collection) if res == nil || !res.IsPublic() { err := &apperror.Err{ Code: "unknown_resource", Message: fmt.Sprintf("The resource '%v' does not exist", collection), } return kit.NewErrorResponse(err), false } response, err := Find(res, request) if err != nil { response = kit.NewErrorResponse(err) } // If response contains a count and the request a "perPage" param, add a total_pages param // to meta. perPage, err2 := request.GetContext().Int("per_page") meta := response.GetMeta() if meta != nil && err2 == nil { count, ok := meta["count"] if ok { meta["total_pages"] = math.Ceil(float64(count.(int)) / float64(perPage)) } } return response, false }
func HandleDelete(registry kit.Registry, request kit.Request) (kit.Response, bool) { collection := request.GetContext().MustString("collection") id := request.GetContext().MustString("id") res := registry.Resource(collection) if res == nil || !res.IsPublic() { resp := kit.NewErrorResponse("unknown_resource", fmt.Sprintf("The resource '%v' does not exist", collection)) return resp, false } return res.ApiDelete(id, request), false }
func Update(registry kit.Registry, request kit.Request) (kit.Response, apperror.Error) { collection := request.GetContext().MustString("collection") res := registry.Resource(collection) if res == nil || !res.IsPublic() { return nil, &apperror.Err{ Code: "unknown_resource", Message: fmt.Sprintf("The resource '%v' does not exist", collection), } } model, ok := request.GetData().(kit.Model) if !ok { return nil, apperror.New("invalid_data_no_model", "Node model data in request.") } response := res.ApiUpdate(model, request) return response, nil }
func UnserializeRequestMiddleware(registry kit.Registry, request kit.Request) (kit.Response, bool) { // Try to parse json in body. Ignore error since body might not contain json. contentType := request.GetHttpRequest().Header.Get("Content-Type") if strings.Contains(contentType, "json") { // Only read the HTTP body automatically for json content type requests, // since some handlers might need to read it themselfes (see the files package resource). if err := request.ReadHttpBody(); err != nil { return kit.NewErrorResponse(err, "http_body_read_error"), false } else { if request.GetRawData() != nil { if err := request.ParseJsonData(); err != nil { return kit.NewErrorResponse(err, "invalid_json_body", true), false } if request.GetData() != nil { // Successfully parsed json body. // Now try to unserialize. // Determine serializer. serializer := registry.DefaultSerializer() // Check if a custom serializer was specified. if name := request.GetContext().String("request-serializer"); name != "" { serializer = registry.Serializer(name) } if serializer == nil { return kit.NewErrorResponse("unknown_serializer", fmt.Sprintf("The specified request serializer does not exist")), false } else { if err := request.Unserialize(serializer); err != nil { return kit.NewErrorResponse(err, "request_unserialize_error", true), false } } } } } } return nil, false }
func RequestLoggerMiddleware(registry kit.Registry, r kit.Request, response kit.Response) (kit.Response, bool) { // Calculate time taken. rawStarted, ok1 := r.GetContext().Get("startTime") rawFinished, ok2 := r.GetContext().Get("endTime") timeTaken := int64(-1) if ok1 && ok2 { started := rawStarted.(time.Time) finished := rawFinished.(time.Time) timeTaken = int64(finished.Sub(started) / time.Millisecond) } // Log the request. method := r.GetHttpMethod() path := r.GetPath() if response.GetError() != nil { registry.Logger().WithFields(logrus.Fields{ "frontend": r.GetFrontend(), "action": "request", "method": method, "path": path, "status": response.GetHttpStatus(), "err": response.GetError(), "milliseconds": timeTaken, }).Errorf("%v: %v - %v - %v", response.GetHttpStatus(), method, path, response.GetError()) } else { registry.Logger().WithFields(logrus.Fields{ "frontend": r.GetFrontend(), "action": "request", "method": method, "path": path, "status": response.GetHttpStatus(), "milliseconds": timeTaken, }).Debugf("%v: %v - %v", response.GetHttpStatus(), method, path) } return nil, false }
func Create(registry kit.Registry, request kit.Request) (kit.Response, apperror.Error) { collection := request.GetContext().MustString("collection") res := registry.Resource(collection) if res == nil || !res.IsPublic() { return nil, &apperror.Err{ Code: "unknown_resource", Message: fmt.Sprintf("The resource '%v' does not exist", collection), } } fmt.Printf("data: %v | %+v\n\n", nil, request.GetData()) model, ok := request.GetData().(kit.Model) if !ok { return nil, apperror.New("invalid_data_no_model", "No model data in request.") } response := res.ApiCreate(model, request) if response.GetError() == nil { response.SetHttpStatus(201) } return response, nil }
func RequestTraceAfterMiddleware(registry kit.Registry, r kit.Request, response kit.Response) (kit.Response, bool) { r.GetContext().Set("endTime", time.Now()) return nil, false }
func RequestTraceMiddleware(registry kit.Registry, r kit.Request) (kit.Response, bool) { r.GetContext().Set("startTime", time.Now()) return nil, false }
func Find(res kit.Resource, request kit.Request) (kit.Response, apperror.Error) { collection := res.Collection() info := res.Backend().ModelInfo(collection) var query *db.Query jsonQuery := request.GetContext().String("query") if jsonQuery != "" { var rawQuery map[string]interface{} if err := json.Unmarshal([]byte(jsonQuery), &rawQuery); err != nil { return nil, apperror.Wrap(err, "invalid_query_json") } rawQuery["collection"] = collection // A custom query was supplied. // Try to parse the query. var err apperror.Error query, err = db.ParseQuery(res.Backend(), rawQuery) if err != nil { return nil, apperror.Wrap(err, "invalid_query", "", false) } } if query == nil { query = res.Backend().Q(collection) } // Check paging parameters. var limit, offset int context := request.GetContext() if context.Has("limit") { val, err := context.Int("limit") if err != nil { return nil, &apperror.Err{ Public: true, Code: "non_numeric_limit_parameter", Message: "The get query contains a non-numeric ?limit", } } limit = val } if context.Has("offset") { val, err := context.Int("offset") if err != nil { return nil, &apperror.Err{ Public: true, Code: "non_numeric_offset_parameter", Message: "The get query contains a non-numeric ?offset", } } offset = val } var page, perPage int if context.Has("page") { val, err := context.Int("page") if err != nil { return nil, &apperror.Err{ Public: true, Code: "non_numeric_page_parameter", Message: "The get query contains a non-numeric ?page", } } page = val } if context.Has("per_page") { val, err := context.Int("per_page") if err != nil { return nil, &apperror.Err{ Public: true, Code: "non_numeric_per_page_parameter", Message: "The get query contains a non-numeric ?per_page", } } perPage = val } if perPage > 0 { limit = perPage } if page > 1 { offset = (page - 1) * limit } if limit > 0 { query.Limit(int(limit)).Offset(int(offset)) } // Add joins. if context.Has("joins") { parts := strings.Split(context.String("joins"), ",") for _, name := range parts { relation := info.FindRelation(name) if relation == nil { return nil, &apperror.Err{ Code: "invalid_join", Message: fmt.Sprintf("Tried to join a NON-existant relationship %v", name), Public: true, } } query.Join(relation.Name()) } } // Add filters. if context.Has("filters") { parts := strings.Split(context.String("filters"), ",") for _, filter := range parts { filterParts := strings.Split(filter, ":") if len(filterParts) != 2 { return nil, &apperror.Err{ Public: true, Code: "invalid_filter", Message: fmt.Sprintf("Invalid filter: %v", filter), } } fieldName := filterParts[0] // COnvert id query to pk field. if fieldName == "id" { fieldName = info.PkAttribute().BackendName() } var typ reflect.Type if attr := info.FindAttribute(fieldName); attr != nil { fieldName = attr.BackendName() typ = attr.Type() } else if rel := info.FindRelation(fieldName); rel != nil { if rel.RelationType() == db.RELATION_TYPE_HAS_ONE { fieldName = rel.LocalField() typ = info.Attribute(rel.LocalField()).Type() } else { return nil, &apperror.Err{ Public: true, Code: "cant_filter_on_relation", Message: fmt.Sprintf("Tried to filter on relationship field %v (only possible for has-one relations)", fieldName), } } } else { return nil, &apperror.Err{ Public: true, Code: "filter_for_inexistant_field", Message: fmt.Sprintf("Tried to filter with inexistant field %v", fieldName), } } converted, err := reflector.R(filterParts[1]).ConvertTo(typ) if err != nil { return nil, &apperror.Err{ Public: true, Code: "inconvertible_filter_value", Message: fmt.Sprintf("Coult not convert filter value %v for field %v (should be %v)", filterParts[1], fieldName, typ), } } query.Filter(fieldName, converted) } } return res.ApiFind(query, request), nil }