http proxy middleware for koa2

Usage no npm install needed!

<script type="module">
  import 2o3tKoa2ProxyMiddleware from 'https://cdn.skypack.dev/@2o3t/koa2-proxy-middleware';



Node.js proxying made simple. Configure proxy middleware with ease for koa2.

Powered by http-proxy-middleware. GitHub stars


Proxy /api requests to http://www.2o3t.cn

const Koa = require('koa');
const app = new Koa();
const proxy = require('@2o3t/koa2-proxy-middleware');

// app.use(proxy({ target: 'http://www.2o3t.cn', changeOrigin: true }));

const Router = require('koa-router');
const router = new Router();
  proxy({ target: 'http://www.2o3t.cn', changeOrigin: true })
// http://localhost:3000/api/foo/bar -> http://www.2o3t.cn/api/foo/bar

All http-proxy options can be used, along with some extra http-proxy-middleware options.

:bulb: Tip: Set the option changeOrigin to true for name-based virtual hosted sites.


$ npm install --save-dev @2o3t/koa2-proxy-middleware
// or
yarn add @2o3t/koa2-proxy-middleware

Core concept

Proxy middleware configuration.

proxy([context,] config)

const proxy = require('@2o3t/koa2-proxy-middleware');

const apiProxy = proxy('/api', { target: 'http://www.2o3t.cn' });
//                   \____/   \_____________________________/
//                     |                    |
//                   context             options

// 'apiProxy' is now ready to be used as middleware in a server.
  • context: Determine which requests should be proxied to the target host. (more on context matching)
  • options.target: target host to proxy to. (protocol + host)

(full list of http-proxy-middleware configuration options)

proxy(uri [, config])

// shorthand syntax for the example above:
const apiProxy = proxy('http://www.2o3t.cn/api');

More about the shorthand configuration.


An example with koa2 server.

const Koa = require('koa');
const app = new Koa();
const proxy = require('@2o3t/koa2-proxy-middleware');

// proxy middleware options
const options = {
  target: 'http://www.2o3t.cn', // target host
  changeOrigin: true, // needed for virtual hosted sites
  ws: true, // proxy websockets
  pathRewrite: {
    '^/api/old-path': '/api/new-path', // rewrite path
    '^/api/remove/path': '/path' // remove base path
  router: {
    // when request.headers.host == 'dev.localhost:3000',
    // override target 'http://www.2o3t.cn' to 'http://localhost:8000'
    'dev.localhost:3000': 'http://localhost:8000'

// create the proxy (without context)
const exampleProxy = proxy(options);


app.use(ctx => {


Context matching

Providing an alternative way to decide which requests should be proxied; In case you are not able to use the server's path parameter to mount the proxy or when you need more flexibility.

RFC 3986 path is used for context matching.

         \_/   \______________/\_________/ \_________/ \__/
          |           |            |            |        |
       scheme     authority       path        query   fragment
  • path matching

    • proxy({...}) - matches any path, all requests will be proxied.
    • proxy('/', {...}) - matches any path, all requests will be proxied.
    • proxy('/api', {...}) - matches paths starting with /api
  • multiple path matching

    • proxy(['/api', '/ajax', '/someotherpath'], {...})
  • wildcard path matching

    For fine-grained control you can use wildcard matching. Glob pattern matching is done by micromatch. Visit micromatch or glob for more globbing examples.

    • proxy('**', {...}) matches any path, all requests will be proxied.
    • proxy('**/*.html', {...}) matches any path which ends with .html
    • proxy('/*.html', {...}) matches paths directly under path-absolute
    • proxy('/api/**/*.html', {...}) matches requests ending with .html in the path of /api
    • proxy(['/api/**', '/ajax/**'], {...}) combine multiple patterns
    • proxy(['/api/**', '!**/bad.json'], {...}) exclusion

    Note: In multiple path matching, you cannot use string paths and wildcard paths together.

  • custom matching

    For full control you can provide a custom function to determine which requests should be proxied or not.

     * @return {Boolean}
    const filter = function(pathname, req) {
      return pathname.match('^/api') && req.method === 'GET';
    const apiProxy = proxy(filter, { target: 'http://www.2o3t.cn' });


http-proxy-middleware configuration options

new options

  • option.proxyBody: [Boolean|Function] Collect the results returned by the agent and assign them to ctx.body. Default: false.
option.proxyBody: true,
// or
option.proxyBody: function(json, proxyRes, req, res, ctx) {
    ctx.body = json;


The MIT License (MIT)

Copyright (c) 2018-2019 Zyao89