Example #1
0
// 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)
}