HTTP Middleware

Video tutorial

  • Writing a middleware for HTTP

RoadRunner HTTP server uses default Golang middleware model which allows you to extend it using custom or community-driven middleware. The simplest service with middleware registration would look like:

HTTP

golang
package middleware

import (
	"net/http"
)

const PluginName = "middleware"

type Plugin struct{}

// to declare plugin
func (p *Plugin) Init() error {
	return nil
}

func (p *Plugin) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// do something
		// ...
		// continue request through the middleware pipeline
		next.ServeHTTP(w, r)
	})
}

// Middleware/plugin name.
func (p *Plugin) Name() string {
	return PluginName
}

Middleware must correspond to the following interface and be named.

gRPC

golang
package middleware

import (
	"net/http"
)

const PluginName = "interceptor"

type Plugin struct{}

// to declare plugin
func (p *Plugin) Init() error {
	return nil
}

func (p *Plugin) Interceptor() grpc.UnaryServerInterceptor {
		// Do something
}

// Middleware/plugin name.
func (p *Plugin) Name() string {
	return PluginName
}

Middleware must correspond to the following interface and be named.


You have to register this service after in the container/plugin.go file in order to properly resolve dependency:

golang
import (
    "middleware"
)

func Plugins() []interface{} {
    return []interface{}{
    // ...
    
    // middleware
    &middleware.Plugin{},
    
    // ...
 }

Or you might use Velox to build the RR binary.

You should also make sure you configure the middleware to be used via the config or the command line otherwise the plugin will be loaded but the middleware will not be used with incoming requests.

yaml
http:
    # provide the name of the plugin as provided by the plugin in the example's case, "middleware"
    middleware: [ "middleware" ]

PSR7 Attributes

You can safely pass values to ServerRequestInterface->getAttributes() using attributes package:

golang
func (s *Service) Middleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		r = attributes.Init(r)
		attributes.Set(r, "key", "value")
		next.ServeHTTP(w, r)
	}
}
Edit this page