// MapController maps a controller to a specified path prefix. // // For more information, see goweb.MapController. func (h *HttpHandler) MapController(options ...interface{}) error { var matcherFuncStartPos int = -1 var path string var controller interface{} if len(options) == 0 { // no arguments is an error panic("goweb: Cannot call MapController with no arguments") } switch options[0].(type) { case string: // (path, controller) if len(options) == 1 { // we need more than just a string panic("goweb: Cannot call MapController without a Controller") } path = options[0].(string) controller = options[1] matcherFuncStartPos = 2 default: // (controller) if restfulController, ok := options[0].(controllers.RestfulController); ok { controller = restfulController path = restfulController.Path() } else { // use the default path controller = options[0] path = paths.PathPrefixForClass(options[0]) } matcherFuncStartPos = 1 } // store the matcher function slice var matcherFuncs []MatcherFunc = findMatcherFuncs(options[matcherFuncStartPos:]...) // get the specialised paths that we might need pathWithID := stewstrings.MergeStrings(path, "/{", RestfulIDParameterName, "}") // e.g. people/123 pathWithOptionalID := stewstrings.MergeStrings(path, "/[", RestfulIDParameterName, "]") // e.g. people/[123] // get the HTTP methods that we will end up mapping collectiveMethods := controllers.OptionsListForResourceCollection(controller) singularMethods := controllers.OptionsListForSingleResource(controller) // BeforeHandler if beforeController, ok := controller.(controllers.BeforeHandler); ok { // map the collective before handler h.MapBefore(collectiveMethods, path, beforeController.Before, matcherFuncs) // map the singular before handler h.MapBefore(singularMethods, pathWithID, beforeController.Before, matcherFuncs) } // AfterHandler if afterController, ok := controller.(controllers.AfterHandler); ok { // map the collective after handler h.MapAfter(collectiveMethods, path, afterController.After, matcherFuncs) // map the singular after handler h.MapAfter(singularMethods, pathWithID, afterController.After, matcherFuncs) } // POST /resource - Create if restfulController, ok := controller.(controllers.RestfulCreator); ok { h.Map(http.MethodPost, path, restfulController.Create, matcherFuncs) } // GET /resource/{id} - Read if restfulController, ok := controller.(controllers.RestfulReader); ok { h.Map(http.MethodGet, pathWithID, func(ctx context.Context) error { return restfulController.Read(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx) }, matcherFuncs) } // GET /resource - ReadMany if restfulController, ok := controller.(controllers.RestfulManyReader); ok { h.Map(http.MethodGet, path, restfulController.ReadMany, matcherFuncs) } // DELETE /resource/{id} - Delete if restfulController, ok := controller.(controllers.RestfulDeletor); ok { h.Map(http.MethodDelete, pathWithID, func(ctx context.Context) error { return restfulController.Delete(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx) }, matcherFuncs) } // DELETE /resource - DeleteMany if restfulController, ok := controller.(controllers.RestfulManyDeleter); ok { h.Map(http.MethodDelete, path, restfulController.DeleteMany, matcherFuncs) } // PUT /resource/{id} - Update if restfulController, ok := controller.(controllers.RestfulUpdater); ok { h.Map(http.MethodPut, pathWithID, func(ctx context.Context) error { return restfulController.Update(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx) }, matcherFuncs) } // PUT /resource - UpdateMany if restfulController, ok := controller.(controllers.RestfulManyUpdater); ok { h.Map(http.MethodPut, path, restfulController.UpdateMany, matcherFuncs) } // POST /resource/{id} - Replace if restfulController, ok := controller.(controllers.RestfulReplacer); ok { h.Map(http.MethodPost, pathWithID, func(ctx context.Context) error { return restfulController.Replace(ctx.PathParams().Get(RestfulIDParameterName).Str(), ctx) }, matcherFuncs) } // HEAD /resource/[id] - Head if restfulController, ok := controller.(controllers.RestfulHead); ok { h.Map(http.MethodHead, pathWithOptionalID, restfulController.Head, matcherFuncs) } // OPTIONS /resource/[id] - Options if restfulController, ok := controller.(controllers.RestfulOptions); ok { h.Map(http.MethodOptions, pathWithOptionalID, restfulController.Options, matcherFuncs) } else { // use the default options implementation h.Map(http.MethodOptions, path, func(ctx context.Context) error { ctx.HttpResponseWriter().Header().Set("Allow", strings.Join(collectiveMethods, ",")) ctx.HttpResponseWriter().WriteHeader(200) return nil }, matcherFuncs) h.Map(http.MethodOptions, pathWithID, func(ctx context.Context) error { ctx.HttpResponseWriter().Header().Set("Allow", strings.Join(singularMethods, ",")) ctx.HttpResponseWriter().WriteHeader(200) return nil }, matcherFuncs) } // everything ok return nil }
func (c *TestController) Path() string { return paths.PathPrefixForClass(c) }