magpie
Loading...
Searching...
No Matches
magpie::Middleware< ContextType > Class Template Referenceabstract

#include <Middleware.hpp>

Public Member Functions

virtual void onRequest (IMiddlewareProcessor< ContextType > *proc, ContextType *ctx, Request &req, Response &res)=0
void next (IMiddlewareProcessor< ContextType > *proc, ContextType *ctx, Request &req, Response &res)

Detailed Description

template<data::IsCommonData ContextType>
class magpie::Middleware< ContextType >

Base definition for middlewares used by magpie.

There's no technical distinction between global and scoped middlewares in their implementation. The call order for middlewares is:

  1. Global
  2. [Reserved (Not implemented): blueprint middlewares]
  3. Per-route middlewares

The order within the middlewares is defined by their declaration order. Middlewares can therefore be arbitrarily chained by their declaration order. See App::registerGlobalMiddlewares and BaseRoute::registerMiddlewares

Chaining is controlled by the next function. To call the next step of the chain, invoke next. Every middleware must invoke next. See the documentation for the next function for more information about the chaining. Example middleware:

class ExampleMiddleware : public magpie::Middleware<MiddlewareTestContext> {
public:
void onRequest(
MiddlewareTestContext* ctx,
) override {
if (req.headers.contains(std::string("x-reject"))) {
// Here, the middleware responds to the request. By not calling `next()`, this middleware ends the chain.
// The route and any middlewares after this point are not invoked.
magpie::Status::Gone,
"Now you're gone"
);
} else {
// Here, we forward to the next handler, either a middleware or a route.
// This may not be present in the final response. If the endpoint does move assignment (the default
// recommendation), any headers set here will be wiped. It's strongly advised you don't alter the request
// until _after_ the `next` call.
res.headers["before"] = "yes";
// Anything before the call to `next` is invoked before the route. Anything after is either invoked after
// the route, or after a middleware later in the chain has created a response.
next(proc, ctx, req, res);
// Request modification after the response is set works as expected, so the `after` header will always be
// present, barring any earlier middlewares further modifying the headers or response.
res.headers["after"] = "yes";
}
}
};
Definition Middleware.hpp:73
void next(IMiddlewareProcessor< ContextType > *proc, ContextType *ctx, Request &req, Response &res)
Definition Middleware.hpp:121
virtual void onRequest(IMiddlewareProcessor< ContextType > *proc, ContextType *ctx, Request &req, Response &res)=0
Definition Middleware.hpp:16
Definition Request.hpp:11
Definition Response.hpp:13
std::unordered_map< std::string, std::string > headers
Definition Response.hpp:17

Member Function Documentation

◆ next()

template<data::IsCommonData ContextType>
void magpie::Middleware< ContextType >::next ( IMiddlewareProcessor< ContextType > * proc,
ContextType * ctx,
Request & req,
Response & res )
inline

Forwards to the next middleware, or to the route of the current middleware is the last middleware in the chain. The call to next separates before and after handlers. Callers do not need to worry about the inner working of this function, only the semantics it implies.

Invocation order

As described in the documentation for this class, the middlewares are called in the same order they're declared. Because the next function directly invokes the next step of the chain, everything after the next is invoked in reverse order. The first middleware to be entered is the last to be exited.

◆ onRequest()

template<data::IsCommonData ContextType>
virtual void magpie::Middleware< ContextType >::onRequest ( IMiddlewareProcessor< ContextType > * proc,
ContextType * ctx,
Request & req,
Response & res )
pure virtual

Called when a request is about to be handled.

The next function must be called somewhere in this function. The call to next is required for a route to be invoked, as well as for the next middleware in the chain to be invoked.

Conceptually, the onRequest call can be thought of as a function containing:

void onRequest(...) {
beforeRequest();
next();
afterRequest();
}

However, the next function being exposed enables the middlewares to also become error handlers. An error handler middleware can simply put a try-catch around the call to next to handle exceptions. This is only necessary if you want a special exception format, as there is a default exception handler built into magpie to keep the server alive through most standard exceptions.

Parameters
procThe middleware processor. This is exclusively used to pass forward to the next call, to tell what to invoke next.
ctxThe context object. Can be used by the middleware.
reqThe request object. Can be used by the middleware.
resThe response object. Can be used by the middleware.

The documentation for this class was generated from the following file: