At its core middleware is just a function that accepts a RouteHandler function as a parameter and returns a new one.

type MiddlewareHandler func(RouteHandler) RouteHandler

An implemented middleware handler then looks like:

func MyMiddleware (next celerity.RouteHandler) celerity.RouteHandler {
  return func(c celerity.Context) celerity.Response {
    // do a thing
    next(c)
  }
}

Each middleware can end in one of two ways:

  1. By returning a response, which will end the middleware chain and respond to the client.
  2. By returning the passed in RouteHandler which will continue the pipeline.

Middleware configuration

The pattern for middleware is to build a factory function will return the MiddwareHandler function. If the middleware has configurable options two factory functions should be used. One that initializes the middleware with sane defaults and another that accepts a configuration structure.

A simple middleware

This example demonstrates a middleware that aliases a userId querystring parameter as id.

func MyMiddleware() celerity.MiddlewareHandler {
  return func(next celerity.RouteHandler) celerity.RouteHandler {
    return func(c celerity.Context) celerity.Response {
      id := c.QueryParams.String("userId")
      if id != "" && c.QueryParams.String("id") == "" {
        c.QueryParams["id"] = id
      }
      return next(c)
    }
  }
}
last modified Friday, June 22, 2018
Previous in Guides
Websockets, Channels, and Rooms
Using the celerity Channel functionality to use web sockets for real time communication
Next in Guides
Testing Routes
Unit and integration tests for routes and route handlers.
Celerity is maintained by 5Sigma. Source code is available at Github.