diff --git a/api/handler/create.go b/api/handler/create.go index 078b929e..ed5ba11c 100644 --- a/api/handler/create.go +++ b/api/handler/create.go @@ -6,7 +6,7 @@ import ( "github.com/rancher/norman/types" ) -func CreateHandler(apiContext *types.APIContext) error { +func CreateHandler(apiContext *types.APIContext, next types.RequestHandler) error { var err error data, err := ParseAndValidateBody(apiContext, true) diff --git a/api/handler/delete.go b/api/handler/delete.go index 63814cd8..2f3b824a 100644 --- a/api/handler/delete.go +++ b/api/handler/delete.go @@ -6,7 +6,7 @@ import ( "github.com/rancher/norman/types" ) -func DeleteHandler(request *types.APIContext) error { +func DeleteHandler(request *types.APIContext, next types.RequestHandler) error { store := request.Schema.Store if store == nil { request.WriteResponse(http.StatusNoContent, nil) diff --git a/api/handler/list.go b/api/handler/list.go index 2f25d64b..fcf2951f 100644 --- a/api/handler/list.go +++ b/api/handler/list.go @@ -7,7 +7,7 @@ import ( "github.com/rancher/norman/types" ) -func ListHandler(request *types.APIContext) error { +func ListHandler(request *types.APIContext, next types.RequestHandler) error { var ( err error data interface{} @@ -24,7 +24,7 @@ func ListHandler(request *types.APIContext) error { } else if request.Link == "" { data, err = store.ByID(request, request.Schema, request.ID) } else { - return request.Schema.LinkHandler(request) + return request.Schema.LinkHandler(request, nil) } if err != nil { diff --git a/api/handler/update.go b/api/handler/update.go index 18237cb7..3c13490f 100644 --- a/api/handler/update.go +++ b/api/handler/update.go @@ -6,7 +6,7 @@ import ( "github.com/rancher/norman/types" ) -func UpdateHandler(apiContext *types.APIContext) error { +func UpdateHandler(apiContext *types.APIContext, next types.RequestHandler) error { data, err := ParseAndValidateBody(apiContext, false) if err != nil { return err diff --git a/api/server.go b/api/server.go index 37557fe0..5a2296d2 100644 --- a/api/server.go +++ b/api/server.go @@ -61,7 +61,7 @@ func NewAPIServer() *Server { DeleteHandler: handler.DeleteHandler, UpdateHandler: handler.UpdateHandler, ListHandler: handler.ListHandler, - LinkHandler: func(*types.APIContext) error { + LinkHandler: func(*types.APIContext, types.RequestHandler) error { return httperror.NewAPIError(httperror.NotFound, "Link not found") }, ErrorHandler: httperror.ErrorHandler, @@ -182,6 +182,7 @@ func (s *Server) handle(rw http.ResponseWriter, req *http.Request) (*types.APICo if action == nil && apiRequest.Type != "" { var handler types.RequestHandler + var nextHandler types.RequestHandler if apiRequest.Link == "" { switch apiRequest.Method { case http.MethodGet: @@ -189,31 +190,36 @@ func (s *Server) handle(rw http.ResponseWriter, req *http.Request) (*types.APICo return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not list "+apiRequest.Schema.Type) } handler = apiRequest.Schema.ListHandler + nextHandler = s.Defaults.ListHandler case http.MethodPost: if !apiRequest.AccessControl.CanCreate(apiRequest, apiRequest.Schema) { return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not create "+apiRequest.Schema.Type) } handler = apiRequest.Schema.CreateHandler + nextHandler = s.Defaults.CreateHandler case http.MethodPut: if !apiRequest.AccessControl.CanUpdate(apiRequest, nil, apiRequest.Schema) { return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not update "+apiRequest.Schema.Type) } handler = apiRequest.Schema.UpdateHandler + nextHandler = s.Defaults.UpdateHandler case http.MethodDelete: if !apiRequest.AccessControl.CanDelete(apiRequest, nil, apiRequest.Schema) { return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not delete "+apiRequest.Schema.Type) } handler = apiRequest.Schema.DeleteHandler + nextHandler = s.Defaults.DeleteHandler } } else { handler = apiRequest.Schema.ListHandler + nextHandler = s.Defaults.ListHandler } if handler == nil { return apiRequest, httperror.NewAPIError(httperror.NotFound, "") } - return apiRequest, handler(apiRequest) + return apiRequest, handler(apiRequest, nextHandler) } else if action != nil { return apiRequest, handleAction(action, apiRequest) } diff --git a/api/writer/headers.go b/api/writer/headers.go index 9ec985bc..ed398016 100644 --- a/api/writer/headers.go +++ b/api/writer/headers.go @@ -16,7 +16,12 @@ func addSchemasHeader(apiContext *types.APIContext) error { return nil } - apiContext.Response.Header().Set("X-Api-Schemas", apiContext.URLBuilder.Collection(schema, apiContext.Version)) + version := apiContext.SchemasVersion + if version == nil { + version = apiContext.Version + } + + apiContext.Response.Header().Set("X-Api-Schemas", apiContext.URLBuilder.Collection(schema, version)) return nil } diff --git a/pkg/subscribe/handler.go b/pkg/subscribe/handler.go index 0aa3e703..4410da29 100644 --- a/pkg/subscribe/handler.go +++ b/pkg/subscribe/handler.go @@ -25,7 +25,7 @@ type Subscribe struct { ProjectID string `norman:"type=reference[project]"` } -func Handler(apiContext *types.APIContext) error { +func Handler(apiContext *types.APIContext, _ types.RequestHandler) error { err := handler(apiContext) if err != nil { logrus.Errorf("Error during subscribe %v", err) diff --git a/types/server_types.go b/types/server_types.go index 8b0d1ef7..f38d7fda 100644 --- a/types/server_types.go +++ b/types/server_types.go @@ -47,7 +47,7 @@ func (r *RawResource) MarshalJSON() ([]byte, error) { type ActionHandler func(actionName string, action *Action, request *APIContext) error -type RequestHandler func(request *APIContext) error +type RequestHandler func(request *APIContext, next RequestHandler) error type QueryFilter func(opts *QueryOptions, data []map[string]interface{}) []map[string]interface{} @@ -87,6 +87,7 @@ type APIContext struct { Schema *Schema Schemas *Schemas Version *APIVersion + SchemasVersion *APIVersion Query url.Values ResponseFormat string ReferenceValidator ReferenceValidator