Basically, middlewares in Koa are just async functions, they can be injected into the app’s request and response cycle. Middlewares are an array of functions that are called one after one, allowing them to access the Koa context and make changes when necessary.
Unlike other frameworks, Koa first invoke “downstream”, then control flows back “upstream”.
When a request comes in, the first middleware is called, you can invoke the next()
function manually, then the function suspends and passes control to the next middleware defined. The next one calls the one after. After there are no middleware to execute, the stack will unwind and go upstream.
If you are familiar with the browser event model, you can think any code before next()
as the “capture” phase and any code after that is the “bubble” phase.
Writing our own middleware
Writing our first middleware is very simple. In this example, I am going to write a middleware that checks if the authorization
request header is set.
1 | async function checkToken(ctx, next) { |
A middleware function takes two parameters: the Koa context and the next middleware to await. In the function body, we can do whatever we like and at some point call the next()
function await the next middleware. This would run the next middleware in the chain, going downstream. Once the last middleware has finished running, it starts getting back upstream, finally getting back to our middleware function. In our case, we don’t have any code after the next()
callback, it does nothing. You might have noticed that we have an early return when the token is not set on the request header, in this case subsequent middleware functions will not be called.
In Eggjs
Eggjs is a framework that built on Koa.
To apply a middleware in an Egg.js project, you can register it globally in config.default.js
and then use the match
or ignore
properties to apply it to specific routes.
- Create the middleware in the
app/middleware
directory.
1 | // app/middleware/customMiddleware.js |
- Configure the middleware globally:
Register the middleware in config.default.js
and use match
or ignore
to specify the routes which it should or should not apply.
1 | // config/config.default.js |