Custom Handler Arguments

Overview

Go-Mojito allows you to create dynamic handlers, it also allows you to provide custom request/response arguments instead of just dependencies.

  • System Component
  • Request/Response-based
  • Not replaceable
  • Inject anything

A common use-case for this feature is extensions that provide a custom context. The stdlib handler/middleware compatibility was achieved using this feature as well.

Quick Start

  1. Create an argument factory function that will be called for each request to a handler that uses your custom argument.

    type CustomHandlerArg struct {
    	ctx router.Context
    }
    
    func (c *CustomHandlerArg) SayHello() {
    	c.ctx.String("Hello World")
    }
    
    func myHandlerArgFactory(ctx router.Context, next router.HandlerFunc) reflect.Value {
    	return reflect.ValueOf(&CustomHandlerArg{ctx: ctx})
    }
  2. Register your factory in the router package so the handler introspector knows about it. You have to register a factory before you attempt to use it in a handler. Make sure the generic type matches the returned value.

    func init() {
        router.RegisterHandlerArgFactory[*CustomHandlerArg](myHandlerArgFactory)
    }
  3. Any handler you register that has a *CustomHandlerArg argument, will now receive the product of your factory function. Think of it as a request-based, transient dependency.

FAQ

Yes! Like most other things in Go-Mojito, you can overwrite builtin/existing factories with your own. This of course only works for interface-based factories.

func init() {
	router.RegisterHandlerArgFactory[mojito.Context](func(ctx router.Context, next router.HandlerFunc) reflect.Value {
      var ctx = ... // Create your instance of your mojito.Context implementation 
		  return reflect.ValueOf(ctx)
	})
}