Using Middlewares with Koa

John Au-Yeung
May 26, 2020 · 4 min read
Photo by David Clode on Unsplash

Koa is a small framework that lets us create backend apps that run on the Node.hs platform.

In this article, we’ll look at how to create our Koa app with our own middlewares.

Middleware is a Building Block of a Koa App

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
ctx.body = 'foo';
});
app.listen(3000);

In the code above, the async function is our middleware. In the function, we just set the body to 'foo' so that we can see that displayed on the screen if we opening our browser.

Cascading Middleware

For instance, we can call it as follows:

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', ms);
});
app.use(async (ctx, next) => {
ctx.body = 'Hello';
});
app.listen(3000);

In the code above, we have 2 middlewares, which we call one by one with passing each one to their own app.use call.

In the first middleware, we set the X-Response-Time response header by setting the ms constant to the current time minus the start time.

To call the 2nd middleware, we call the next function from the 2nd parameter of the middleware function.

In the second middleware, we set the response body of our route by setting ctx.body to 'Hello' .

Therefore, when we make a request to the / route, we get that the body is ‘Hello’ and one of the response headers is X-Response-Time with the number of milliseconds to process the request after the request is made.

Error Handling

For instance, we can handle errors as follows:

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
try {
await Promise.reject('error');
} catch (err) {
ctx.status = err.status || 500;
ctx.body = err.message;
ctx.app.emit('error', err, ctx);
}
});
app.on('error', (err, ctx) => {
console.log(err);
});
app.listen(3000);

In the code above, we have a try...catch block to catch any errors that are thrown, which it’s the case since we have Promise.reject .

Then we called ctx.app.emit to emit the error event, which sends the err object that has the rejection reason from the promise, along with the ctx context object.

Then in the error handler that’s passed in as the 2nd argument as the app.on method call, we log the error.

Now when we make a request to the / route, we see that 'error' is logged in the console.

Using ctx.throw

For instance, we can use it as follows:

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
ctx.throw(500, 'error');
});
app.on('error', (err, ctx) => {
console.log(err);
});
app.listen(3000);

In the code above, we called the ctx.throw method with the error 500 and the error message 'error' .

The error message will be available within the callback that we passed into the app.on method. The error message will be available as the value of the message property.

Photo by Sebastian Pena Lambarri on Unsplash

Using ctx.assert

For instance, we can use it as follows:

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
ctx.assert(ctx.request.accepts('json'), 406);
ctx.body = 'hello';
});
app.on('error', (err, ctx) => {
console.log(err);
});
app.listen(3000);

In the code above, we have called the ctx.assert method as follows:

ctx.assert(ctx.request.accepts('json'), 406);

Now if our request header has the Accept request header that’s like the following:

application/json

Then we’ll get hello’ displayed on the screen.

Otherwise, if our request Accept header is application/atom+xml , then we’ll get the back a 406 response.

Conclusion

We also use middlewares to handle errors. However, instead of passing them to the app.use method, we pass them into the app.on method.

Then we can use methods like ctx.assert and ctx.throw to throw errors, then the error gets sent to the error handler automatically.

The Startup

Get smarter at building your thing. Join The Startup’s +787K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

John Au-Yeung

Written by

Web developer. Subscribe to my email list now at https://thewebdev.info/subscribe/. Email me at hohanga@gmail.com

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +787K followers.

John Au-Yeung

Written by

Web developer. Subscribe to my email list now at https://thewebdev.info/subscribe/. Email me at hohanga@gmail.com

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +787K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store