Koa Unless
raw JSON →Koa Unless is a utility for Koa.js applications that allows developers to conditionally skip middleware execution based on various criteria such as HTTP method, request path (string or regex), file extension, or a custom function. The current stable version, 1.0.7, was last published about 9 years ago (March 2017). Given its age, it relies on older Koa.js conventions (e.g., generator functions for middleware) and CommonJS modules. This package's primary differentiator is its simple, declarative API for conditional middleware, though modern Koa applications often achieve similar functionality with explicit `if` statements or newer conditional middleware libraries. The project appears to be abandoned, with the last commit also around 9 years ago, indicating no active development or compatibility updates for newer Koa versions or Node.js features like ESM.
Common errors
error TypeError: app.use(...) is not a function ↓
yourMiddleware.unless = require('koa-unless'); is called before applying the conditional logic to app.use. error SyntaxError: await is only valid in async function ↓
koa-unless, ensure all integrated middleware (including koa-unless itself, if adapting it) are compatible with either generator functions or async/await consistently. For modern Koa, it's strongly recommended to avoid koa-unless and use native async/await middleware with explicit conditional logic. error this.url is not a function (or similar property access errors within custom condition) ↓
custom condition to a regular function declaration (e.g., function () { return this.url === '/some-path'; }) to correctly bind this to the Koa context (ctx). Warnings
breaking Koa-unless was designed for Koa v1.x, which used generator functions for middleware (e.g., `function *(next)`). Modern Koa (v2.x and above) exclusively uses `async/await` functions. While it might still function for simple cases, full compatibility with the cascading `async/await` middleware pattern is not guaranteed, and unexpected behavior may occur. ↓
deprecated This package is abandoned; its last publish was approximately 9 years ago. There will be no further updates for bug fixes, security patches, or compatibility with newer Node.js or Koa versions. ↓
gotcha Koa-unless does not ship with TypeScript type definitions. Using it in a TypeScript project will require creating custom declaration files (`.d.ts`) or disabling type checks for its usage, which can reduce type safety and developer experience. ↓
gotcha The `custom` option for conditional logic provides a `this` context that refers to Koa's `ctx` object. However, if the custom function is an arrow function, `this` will not be bound to `ctx`, leading to unexpected behavior. ↓
gotcha Due to its CommonJS nature, `koa-unless` cannot be directly `import`ed in an ES module environment without specific Node.js loader configurations or transpilation. Many modern Koa projects are now ESM-first. ↓
Install
npm install koa-unless yarn add koa-unless pnpm add koa-unless Imports
- unless wrong
import unless from 'koa-unless';correctconst unless = require('koa-unless'); - mymid.unless
mymid.unless = require('koa-unless'); - app.use(middleware.unless({ ... }))
app.use(static.unless({ path: ['/index.html', '/'] }));
Quickstart
const Koa = require('koa');
const unless = require('koa-unless');
const serve = require('koa-static');
const app = new Koa();
// A simple authentication middleware
const requiresAuth = async (ctx, next) => {
if (!ctx.headers.authorization || ctx.headers.authorization !== 'Bearer my-secret-token') {
ctx.status = 401;
ctx.body = 'Unauthorized';
return;
}
await next();
};
// Make the authentication middleware conditional
// It will run for all paths EXCEPT '/public' and '/login'
requiresAuth.unless = unless;
app.use(requiresAuth.unless({ path: ['/public', '/login'] }));
// Serve static files from a 'public' directory, unless the method is OPTIONS
const staticMiddleware = serve(__dirname + '/public');
staticMiddleware.unless = unless;
app.use(staticMiddleware.unless({ method: 'OPTIONS' }));
// Example public route, accessible without auth
app.use(async (ctx, next) => {
if (ctx.path === '/public') {
ctx.body = 'This is a public page!';
} else {
await next();
}
});
// Example login route, accessible without auth
app.use(async (ctx) => {
if (ctx.path === '/login') {
ctx.body = 'Login page, no auth required here.';
} else if (!ctx.body) {
// If no middleware has set a body yet (meaning auth passed, or path was /public or /login)
ctx.body = 'Protected content! You are authorized.';
}
});
// Create a simple 'public' directory for the static middleware
const fs = require('fs');
const path = require('path');
const publicDirPath = path.join(__dirname, 'public');
if (!fs.existsSync(publicDirPath)) {
fs.mkdirSync(publicDirPath);
}
fs.writeFileSync(path.join(publicDirPath, 'index.html'), '<h1>Hello from static!</h1>');
app.listen(3000, () => {
console.log('Koa app listening on port 3000');
console.log('Try:');
console.log(' curl http://localhost:3000/public');
console.log(' curl http://localhost:3000/login');
console.log(' curl http://localhost:3000/ (will be unauthorized)');
console.log(' curl -H "Authorization: Bearer my-secret-token" http://localhost:3000/');
});