Angelos Orfanakos

A simple access log middleware for Koa.js

I recently needed a simple access log middleware for Koa.js to log incoming requests, similar to what all web servers have:

127.0.0.1 - - [19/Nov/2019:23:28:20 +0200] "GET /place/autocomplete HTTP/1.1" 200 1055

I found koa-accesslog but was disappointed to find out it’s unmaintained and written for Koa.js 1.x, using its soon-to-be-deprecated generator syntax and throwing warnings about it in 2.x. It’s also hard-coding the HTTP version and uses Moment.js for formatting the date, which is not ideal.

So I decided to rewrite it to address all of the above issues. Here’s the result:

const util = require('util');
const format = require('date-fns/format');
// ip, date, method, path, http version, status and length
const LOG_FORMAT = '%s - - [%s] "%s %s HTTP/%s" %d %s\n';
const DATE_FORMAT = 'd/MMM/yyyy:HH:mm:ss xx';

module.exports = function(stream) {  stream = stream || process.stdout;

  return async function accesslog(ctx, next) {    await next();
    stream.write(
      util.format(
        LOG_FORMAT,
        ctx.ip,
        format(new Date(), DATE_FORMAT),        ctx.method,
        ctx.path,
        ctx.req.httpVersion,        ctx.status,
        ctx.length ? ctx.length.toString() : '-'
      )
    );
  };
};

Things to note:

  • It’s using date-fns to format the date and time of the request (lines 2, 18). So you will need to run yarn add date-fns or npm install date-fns in your project.
  • It accepts an optional stream argument to log each request to (defaults to process.stdout)
  • It’s using the new 2.x async/await middleware syntax of Koa.js 2.x (lines 11, 12)
  • It logs the HTTP version of the request (line 21)

Here’s how to use it:

const Koa = require('koa');
const accesslog = require('./accesslog'); // local middleware file

const app = new Koa();

app.use(accesslog());
// ...
app.listen(3000);

Since I’m currently still experimenting with Koa.js and trying to decide between it and Express.js, I haven’t released this as a library yet. If you’d be interested, please let me know.