Creating Middleware
A Mach middleware can be any class that provides an invoke() method with the expected signature.
There is no middleware base class to inherit from.
Define a Middleware
Section titled “Define a Middleware”A middleware class implements:
void invoke(mach::Context& context, mach::Next& next);For example:
class LoggingMiddleware {public: explicit LoggingMiddleware(mach::Logger& logger) : m_logger(logger) {}
void invoke(mach::Context& context, mach::Next& next) { m_logger.info("Before handler");
context.response.setHeader("X-Middleware", "Logging");
next();
m_logger.info("After handler"); }
private: mach::Logger& m_logger;};Mach calls invoke() when a request reaches the middleware.
The two parameters provide access to the current request pipeline:
mach::Context& contextexposes the current request and response.mach::Next& nextrepresents the next step in the pipeline.
Generate a Middleware
Section titled “Generate a Middleware”The Mach CLI can generate a middleware class for you:
mach generate middleware loggingThis creates a LoggingMiddleware with the required invoke() method, ready for your middleware logic.
Continue the Pipeline
Section titled “Continue the Pipeline”Call next() to continue processing:
void invoke(mach::Context& context, mach::Next& next) { // Runs before later middleware or the endpoint
next();
// Runs after later middleware or the endpoint}Code before next() runs on the way into the pipeline. Code after it runs when control returns.
This makes middleware useful for behavior that needs to surround endpoint execution.
Short-Circuit the Pipeline
Section titled “Short-Circuit the Pipeline”A middleware does not have to call next().
If it produces a response and returns without invoking the next step, later middleware and the matched endpoint are skipped:
void invoke(mach::Context& context, mach::Next& next) { if (!context.request.containsHeader("X-Required")) { context.response.status(mach::http::StatusCode::BadRequest); context.response.body("Missing required header");
return; }
next();}This is known as short-circuiting the pipeline.
It is useful when the middleware can determine that the request should not continue.
Access Request and Response Data
Section titled “Access Request and Response Data”Middleware receives the same mach::Context& used by minimal API handlers.
For example:
void invoke(mach::Context& context, mach::Next& next) { const auto method = context.request.method();
context.response.setHeader("X-Processed-By", "Mach");
next();}This allows middleware to inspect or modify request and response data before and after endpoint execution.
Middleware Dependencies
Section titled “Middleware Dependencies”Middleware classes can receive dependencies through their constructor:
class LoggingMiddleware {public: explicit LoggingMiddleware(mach::Logger& logger) : m_logger(logger) {}
void invoke(mach::Context& context, mach::Next& next) { m_logger.info("Before handler");
next();
m_logger.info("After handler"); }
private: mach::Logger& m_logger;};The dependency list is provided when the middleware is registered.
Registration and dependency declaration are covered in the next guide.
Next, you’ll learn how to register middleware and control its position in the request pipeline.