Koa HTTP Proxy Middleware
`koa-proxies` is an HTTP proxy middleware specifically designed for Koa@2.x applications, providing robust proxying capabilities powered by the underlying `http-proxy` library. It enables developers to easily route incoming requests to different target servers, a common pattern for API forwarding, bypassing CORS restrictions during development, or orchestrating microservices. The library currently stands at version 0.12.4. While its latest release dates indicate a more maintenance-focused cadence rather than active feature development (last significant features around 2020), it remains a functional and widely used choice for Koa projects. Key differentiators include its flexible option handling, allowing both static configurations and dynamic determination of proxy settings via a function, and integrated support for `path-match` for advanced routing logic. It also provides built-in TypeScript type definitions since version 0.11.0, enhancing developer experience in TypeScript-based Koa applications.
Common errors
-
TypeError: ctx.request.body is undefined
cause `koa-proxies` is placed after `koa-bodyparser` or a similar body-parsing middleware, causing the request stream to be consumed before `koa-proxies` can process it.fixEnsure `koa-proxies` middleware is always applied before any middleware that parses or consumes the request body, such as `koa-bodyparser`. For example: `app.use(proxy('/api', {...})); app.use(bodyParser());` -
Proxy error: connect ECONNREFUSED
cause The target server specified in the `options.target` configuration is not running, is inaccessible, or is listening on a different address/port than configured.fixVerify that the backend service (e.g., `http://localhost:3001` in the quickstart) is actively running and reachable from the server hosting your Koa application. Check network configurations, firewall rules, or DNS settings if the target is remote. -
Error: Can't set headers after they are sent.
cause This typically occurs when a proxy request fails, and an error handler attempts to send a response after the `http-proxy` library has already sent headers or a partial response.fixImplement robust error handling within the `options.events.error` callback. Before sending a response in the error handler, check `res.headersSent` to avoid attempting to set headers on an already-responded stream. For example: `if (!res.headersSent) { res.writeHead(500); res.end('Proxy error'); }`
Warnings
- gotcha Placing `koa-proxies` after `koa-bodyparser` (or any other middleware that consumes the request body stream) in the middleware chain can lead to requests hanging or unexpected behavior, especially for POST/PUT requests with bodies.
- breaking The internal path resolution logic was updated in `v0.9.0` to utilize the modern `URL` constructor instead of the deprecated Node.js `url.resolve` method.
- gotcha Prior to `v0.6.1`, there was a bug where `http-proxy` events (e.g., `error`, `proxyReq`, `proxyRes`) were registered multiple times, which could potentially lead to memory leaks or incorrect event handling logic.
Install
-
npm install koa-proxies -
yarn add koa-proxies -
pnpm add koa-proxies
Imports
- proxy
import { proxy } from 'koa-proxies';import proxy from 'koa-proxies';
- proxy (CommonJS)
const proxy = require('koa-proxies'); - KoaProxyOptions
import { KoaProxyOptions } } from 'koa-proxies';import type { KoaProxyOptions } from 'koa-proxies';
Quickstart
import Koa from 'koa';
import proxy from 'koa-proxies';
import httpsProxyAgent from 'https-proxy-agent'; // Install if needed: npm i https-proxy-agent
const app = new Koa();
// Example 1: Basic proxy for a fixed path
app.use(proxy('/api', {
target: 'http://localhost:3001', // Your target API server
changeOrigin: true, // Changes the origin of the host header to the target URL
rewrite: path => path.replace('/api', ''), // Rewrites the path from /api/users to /users
logs: true // Enables logging of proxy requests to console
}));
// Example 2: Dynamic proxy with path parameters
app.use(proxy('/users/:id', (params, ctx) => {
return {
target: 'https://jsonplaceholder.typicode.com', // A public API for testing
changeOrigin: true,
rewrite: () => `/users/${params.id}`, // Dynamically rewrite path based on URL parameter
logs: (ctx, target) => {
console.log(`[Proxy Log] ${ctx.method} ${ctx.path} -> ${target}`);
},
// Example of using a proxy agent (install 'https-proxy-agent' if needed)
// agent: new httpsProxyAgent('http://your.proxy.server:port') // Remove if not using a proxy agent
};
}));
app.listen(3000, () => {
console.log('Koa proxy server listening on http://localhost:3000');
console.log('Try visiting http://localhost:3000/api/posts/1 (proxies to http://localhost:3001/posts/1)');
console.log('Or http://localhost:3000/users/1 (proxies to https://jsonplaceholder.typicode.com/users/1)');
});