Categories
Koa Nodejs

Using Middlewares with Koa

Spread the love

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

Koa apps are made up of middlewares. We can define and use it by writing the following code:

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

We can chain more than one middlewares together with the next function, which is available from the parameter of the middleware function. It’s the 2nd parameter.

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

We use error handling to catch errors and handle them. To listen to error events and handle them, we call the app.on method to catch the error.

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

The ctx.throw method lets us throw an error in our app. It takes the response code as the first argument and the error message as the 2nd argument.

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.

Using ctx.assert

Koa’s context object also has the ctx.assert method that throws an error if the condition isn’t met. The condition is passed into the first argument of the method. The 2nd argument is the response code that we want to send if the condition isn’t met.

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

With Koa middlewares, we can build simple apps by writing one or more middleware. If we have more than one middleware, then we can chain them together by calling the next function that’s available from the parameter of the middleware function.

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *