Middleware
Last updated
Last updated
Sometimes, it becomes to recycle code to run on multiple routes. Angel allows for this in the form of middleware. Middleware are frequently used as authorization filters, or to serialize database data for use in subsequent routes. Middleware in Angel can be any route handler, whether a function or arbitrary data. You can also throw exceptions in middleware.
A middleware should return either true
or false
. If false
is returned, no further routes will be executed. If true
is returned, route evaluation will continue. (more on request handler return values ).
In practice, you will only need to write a return
statement when you are returning true
.
As you can imagine, this is perfect for authorization filters.
You can call a router's chain
method, or assign middleware in the middleware
parameter of a route method.
Though this might at first seem redundant, there are actually reasons for all three existing.
By convention, though, follow these readability rules when building Angel servers:
Routes with no middleware should not use chain
, app.chain
, or `middleware. Self-explanatory.
Routes with one middleware and one handler should use app.chain([...])
when:
The construction of all the middleware does not take more than one line.
In all other cases, use the chain
meta-handler.
Avoid using middleware: ...
directly, as it is used internally package:route
.
For more complicated middleware, you can also create a class.
Canonically, when using a class as a request handler, it should provide a handleRequest(RequestContext, ResponseContext)
method. This pattern is seen throughout many Angel plugins, such as VirtualDirectory
or Proxy
.
Take the following example. At first glance, it might not be very easy to read.
In general, consider it a code smell to stack multiple handlers onto a route like this; it hampers readability, and in general just doesn't look good.
Instead, when you have multiple handlers, you can split them into multiple chain
calls, assigned to variables, which have the added benefit of communicating what each set of middleware does:
Tip: Prefer using named functions as handlers, rather than anonymous functions, or concrete objects.
To add a handler that handles every request, call app.fallback
. This is merely shorthand for calling app.all('*', <handler>)
. (more info on request lifecycle ).
The reason for this is that a name like handleRequest
makes it very clear to anyone reading the code what it is supposed to do. This is the same rationale behind providing a configureServer
method.
Take a good look at in Angel!