Axum Middleware

Roadster's HTTP service has full support for any Axum (or Tower) middleware, many of which are provided by default. It's also possible to register middleware that Roadster doesn't provide by default, or even create and provide your own custom middleware.

Default middleware

For the most up to date list of middleware provided by Roadster, see the module's docs.rs page

All of the default middleware can be configured via the app's config files. All middleware have at least the following config fields:

  • enable: Whether the middleware is enabled. If not provided, the middleware enablement falls back to the value of the service.http.middleware.default-enable field.
  • priority: The priority in which the middleware will run. Lower values (including negative numbers) run before higher values. The middlewares provided by Roadster have priorities between -10,000 (runs first) and 10,000 (runs later) by default, though these values can be overridden via configs. If the order your middleware runs in doesn't matter, simply set to 0.

Custom middleware

Custom middleware can be provided by implementing the Middleware trait. As a convenience, custom middleware can also be applied using the AnyMiddleware utility. This is useful, for example, for middleware that can be built using Axum's from_fn method.

const BASE: &str = "/api";

/// Set up the [`HttpServiceBuilder`]. This will then be registered with the
/// [`roadster::service::registry::ServiceRegistry`].
pub async fn http_service(state: &AppContext) -> RoadsterResult<HttpServiceBuilder<AppContext>> {
    HttpServiceBuilder::new(Some(BASE), state)
        .api_router(ApiRouter::new().api_route(
            &build_path(BASE, "/example_b"),
            get_with(example_b::example_b_get, example_b::example_b_get_docs),
        ))
        .middleware(
            AnyMiddleware::builder()
                .name("custom-middleware")
                .apply(|router, _state| {
                    let router = router.layer(axum::middleware::from_fn(custom_middleware_fn));
                    Ok(router)
                })
                .build(),
        )
}

async fn custom_middleware_fn(request: Request, next: Next) -> Response {
    info!("Running custom middleware");

    next.run(request).await
}