Middlewares
In Marble.js, middlewares are streams of side-effects that can be composed and plugged-in to our request/event lifecycle to perform certain actions before reaching the designated Effect.
Building your own middleware
Because everything here is a stream, the plugged-in middlewares are also based on a similar Effect interface.
By default, framework comes bundled with composable middlewares like: logging, request body parsing or request validator. Below you can see how simple can look a dummy HTTP request logging middleware.
The example above performs I/O operation for every request that comes through the stream. As you can see, the middleware, compared to the basic effect, must return the processed request at the end.
In order to use our custom middleware, we need to attach the defined middleware to the httpListener
config.
Parameterized middleware
There are some cases when our custom middleware needs to be parameterized - for example, the dummy logger$
middleware should log request URL's conditionally. To achieve this behavior we can make our middleware function curried, where the last returned function should conform toHttpMiddlewareEffect
interface.
The improved logging middleware, can be composed like in the following example:
Sending a response earlier
Some types of middlewares need to send an HTTP response earlier. For this case Marble.js exposes a dedicated req.res.send
method which allows to send an HTTP response using the same common interface that we use for sending a response inside API Effects. The mentioned method returns an empty Observable (Observable that immediately completes) as a result, so it can be composed easily inside a middleware pipeline.
If the HTTP response is sent earlier than inside the target Effect, the execution of all following middlewares and Effects will be skipped.
Middlewares composition
You can compose middlewares in four ways:
globally (inside
httpListener
configuration object),inside grouped effects (via
combineRoutes
function),or by composing it directly inside Effect request pipeline.
via Effect
There are many scenarios where we would like to apply middlewares inside our API Effects. One of them is to authorize only specific endpoints. Going to meet the requirements, Marble.js allows us to compose them using dedicated use operator, directly inside request stream pipeline.
Lets say we have an endpoint for getting list of all users, but also we would like to make it secure, and available only for authorized users. All we need to do is to compose authorization middleware using dedicated for this case use
operator.
The example implementation of authorize$
middleware can look like in the following snippet:
via combineRoutes
There are some cases where you would like to compose a bunch of middlewares before grouped routes, e.g. to authorize only a selected group of endpoints. Instead of composing middlewares for each route separately, you can also compose them via extended second parameter of combineRoutes()
function.
via httpListener
If your middleware should operate globally, e.g. in case of request logging, the best place is to compose it inside httpListener
. In this case the middleware will operate on each request that goes through your HTTP server.
The stacking order of middlewares inside httpListener
and combineRoutes
matters, because middlewares are run sequentially (one after another).
Last updated