Node.js proxying made simple. Configure proxy middleware with ease for connect, express, browser-sync and many more.
Powered by the popular Nodejitsu http-proxy
.
This page is showing documentation for version v2.x.x (release notes)
If you're looking for v0.x documentation. Go to: https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme
Proxy /api
requests to http://www.example.org
// javascript
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
app.listen(3000);
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
// typescript
import * as express from 'express';
import { createProxyMiddleware, Filter, Options, RequestHandler } from 'http-proxy-middleware';
const app = express();
app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
app.listen(3000);
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
All http-proxy
options can be used, along with some extra http-proxy-middleware
options.
💡 Tip: Set the option changeOrigin
to true
for name-based virtual hosted sites.
- Install
- Core concept
- Example
- Context matching
- Options
- Shorthand
- WebSocket
- Intercept and manipulate requests
- Intercept and manipulate responses
- Working examples
- Recipes
- Compatible servers
- Tests
- Changelog
- License
$ npm install --save-dev http-proxy-middleware
Proxy middleware configuration.
const { createProxyMiddleware } = require('http-proxy-middleware');
const apiProxy = createProxyMiddleware('/api', { target: 'http://www.example.org' });
// \____/ \_____________________________/
// | |
// 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)
// shorthand syntax for the example above:
const apiProxy = createProxyMiddleware('http://www.example.org/api');
More about the shorthand configuration.
An example with express
server.
// include dependencies
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
// proxy middleware options
/** @type {import('http-proxy-middleware/dist/types').Options} */
const options = {
target: 'http://www.example.org', // 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.example.org' to 'http://localhost:8000'
'dev.localhost:3000': 'http://localhost:8000',
},
};
// create the proxy (without context)
const exampleProxy = createProxyMiddleware(options);
// mount `exampleProxy` in web server
const app = express();
app.use('/api', exampleProxy);
app.listen(3000);
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.
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
-
path matching
createProxyMiddleware({...})
- matches any path, all requests will be proxied.createProxyMiddleware('/', {...})
- matches any path, all requests will be proxied.createProxyMiddleware('/api', {...})
- matches paths starting with/api
-
multiple path matching
createProxyMiddleware(['/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.
createProxyMiddleware('**', {...})
matches any path, all requests will be proxied.createProxyMiddleware('**/*.html', {...})
matches any path which ends with.html
createProxyMiddleware('/*.html', {...})
matches paths directly under path-absolutecreateProxyMiddleware('/api/**/*.html', {...})
matches requests ending with.html
in the path of/api
createProxyMiddleware(['/api/**', '/ajax/**'], {...})
combine multiple patternscreateProxyMiddleware(['/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 = createProxyMiddleware(filter, { target: 'http://www.example.org', });
-
option.pathRewrite: object/function, rewrite target's url path. Object-keys will be used as RegExp to match paths.
// rewrite path pathRewrite: {'^/old/api' : '/new/api'} // remove path pathRewrite: {'^/remove/api' : ''} // add base path pathRewrite: {'^/' : '/basepath/'} // custom rewriting pathRewrite: function (path, req) { return path.replace('/api', '/base/api') } // custom rewriting, returning Promise pathRewrite: async function (path, req) { const should_add_something = await httpRequestToDecideSomething(path); if (should_add_something) path += "something"; return path; }
-
option.router: object/function, re-target
option.target
for specific requests.// Use `host` and/or `path` to match requests. First match will be used. // The order of the configuration matters. router: { 'integration.localhost:3000' : 'http://localhost:8001', // host only 'staging.localhost:3000' : 'http://localhost:8002', // host only 'localhost:3000/api' : 'http://localhost:8003', // host + path '/rest' : 'http://localhost:8004' // path only } // Custom router function (string target) router: function(req) { return 'http://localhost:8004'; } // Custom router function (target object) router: function(req) { return { protocol: 'https:', // The : is required host: 'localhost', port: 8004 }; } // Asynchronous router function which returns promise router: async function(req) { const url = await doSomeIO(); return url; }
-
option.logLevel: string, ['debug', 'info', 'warn', 'error', 'silent']. Default:
'info'
-
option.logProvider: function, modify or replace log provider. Default:
console
.// simple replace function logProvider(provider) { // replace the default console log provider. return require('winston'); }
// verbose replacement function logProvider(provider) { const logger = new (require('winston').Logger)(); const myCustomProvider = { log: logger.log, debug: logger.debug, info: logger.info, warn: logger.warn, error: logger.error, }; return myCustomProvider; }
Subscribe to http-proxy events:
-
option.onError: function, subscribe to http-proxy's
error
event for custom error handling.function onError(err, req, res, target) { res.writeHead(500, { 'Content-Type': 'text/plain', }); res.end('Something went wrong. And we are reporting a custom error message.'); }
-
option.onProxyRes: function, subscribe to http-proxy's
proxyRes
event.function onProxyRes(proxyRes, req, res) { proxyRes.headers['x-added'] = 'foobar'; // add new header to response delete proxyRes.headers['x-removed']; // remove header from response }
-
option.onProxyReq: function, subscribe to http-proxy's
proxyReq
event.function onProxyReq(proxyReq, req, res) { // add custom header to request proxyReq.setHeader('x-added', 'foobar'); // or log the req }
-
option.onProxyReqWs: function, subscribe to http-proxy's
proxyReqWs
event.function onProxyReqWs(proxyReq, req, socket, options, head) { // add custom header proxyReq.setHeader('X-Special-Proxy-Header', 'foobar'); }
-
option.onOpen: function, subscribe to http-proxy's
open
event.function onOpen(proxySocket) { // listen for messages coming FROM the target here proxySocket.on('data', hybridParseAndLogMessage); }
-
option.onClose: function, subscribe to http-proxy's
close
event.function onClose(res, socket, head) { // view disconnected websocket connections console.log('Client disconnected'); }
The following options are provided by the underlying http-proxy library.
-
option.target: url string to be parsed with the url module
-
option.forward: url string to be parsed with the url module
-
option.agent: object to be passed to http(s).request (see Node's https agent and http agent objects)
-
option.ssl: object to be passed to https.createServer()
-
option.ws: true/false: if you want to proxy websockets
-
option.xfwd: true/false, adds x-forward headers
-
option.secure: true/false, if you want to verify the SSL Certs
-
option.toProxy: true/false, passes the absolute URL as the
path
(useful for proxying to proxies) -
option.prependPath: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path
-
option.ignorePath: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required).
-
option.localAddress : Local interface string to bind for outgoing connections
-
option.changeOrigin: true/false, Default: false - changes the origin of the host header to the target URL
-
option.preserveHeaderKeyCase: true/false, Default: false - specify whether you want to keep letter case of response header key
-
option.auth : Basic authentication i.e. 'user:password' to compute an Authorization header.
-
option.hostRewrite: rewrites the location hostname on (301/302/307/308) redirects.
-
option.autoRewrite: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
-
option.protocolRewrite: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
-
option.cookieDomainRewrite: rewrites domain of
set-cookie
headers. Possible values:false
(default): disable cookie rewriting- String: new domain, for example
cookieDomainRewrite: "new.domain"
. To remove the domain, usecookieDomainRewrite: ""
. - Object: mapping of domains to new domains, use
"*"
to match all domains.
For example keep one domain unchanged, rewrite one domain and remove other domains:cookieDomainRewrite: { "unchanged.domain": "unchanged.domain", "old.domain": "new.domain", "*": "" }
-
option.cookiePathRewrite: rewrites path of
set-cookie
headers. Possible values:false
(default): disable cookie rewriting- String: new path, for example
cookiePathRewrite: "/newPath/"
. To remove the path, usecookiePathRewrite: ""
. To set path to root usecookiePathRewrite: "/"
. - Object: mapping of paths to new paths, use
"*"
to match all paths. For example, to keep one path unchanged, rewrite one path and remove other paths:cookiePathRewrite: { "/unchanged.path/": "/unchanged.path/", "/old.path/": "/new.path/", "*": "" }
-
option.headers: object, adds request headers. (Example:
{host:'www.example.org'}
) -
option.proxyTimeout: timeout (in millis) when proxy receives no response from target
-
option.timeout: timeout (in millis) for incoming requests
-
option.followRedirects: true/false, Default: false - specify whether you want to follow redirects
-
option.selfHandleResponse true/false, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the
proxyRes
event -
option.buffer: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option:
'use strict'; const streamify = require('stream-array'); const HttpProxy = require('http-proxy'); const proxy = new HttpProxy(); module.exports = (req, res, next) => { proxy.web( req, res, { target: 'http://localhost:4003/', buffer: streamify(req.rawBody), }, next ); };
Use the shorthand syntax when verbose configuration is not needed. The context
and option.target
will be automatically configured when shorthand is used. Options can still be used if needed.
createProxyMiddleware('http://www.example.org:8000/api');
// createProxyMiddleware('/api', {target: 'http://www.example.org:8000'});
createProxyMiddleware('http://www.example.org:8000/api/books/*/**.json');
// createProxyMiddleware('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
createProxyMiddleware('http://www.example.org:8000/api', { changeOrigin: true });
// createProxyMiddleware('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
If you want to use the server's app.use
path
parameter to match requests;
Create and mount the proxy without the http-proxy-middleware context
parameter:
app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));