HTTP Proxy Middleware

By Raúl on Jan 14, 2023
Image courtesy of unsplash

The http-proxy-middleware [HMP] exposes the createProxyMiddleware which returns an Express middleware.

It’s signature is

createProxyMiddleware(context, {
	...options
})

When used like

createProxyMiddleware({
	...options
})

from the proxy middleware perspective, this middleware has no context (which means every request it gets should be proxied to target).

createProxyMiddleware({...options}) - matches any path, all requests will be proxied.
createProxyMiddleware('/', {...options}) - matches any path, all requests will be proxied.
createProxyMiddleware('/api', {...options}) - matches paths starting with /api
const myProxyFunction = createProxyMiddleware({
    target: 'http://some.target.com',
    changeOrigin: true, // for virtual hosted sites, changes Host HTTP header to match to target's host and avoid "Direct IP access not allowed" errors
    logLevel: 'debug',
    logger: console
  });

CONTROL VIA EXPRESS ROUTE

From the Express perspective

//app.use(expressRoutePath, middlewareFunction);
app.use('/myExpressRoutePath', myProxyFunction);

When used like this, the logger debug option will log a [HMP] mapping from /http://some.target.com because it is mapping from a root path from the middleware perspective, as the createMiddleware did not specify a particular context.

info: [HPM] Proxy created: /  -> http://jsonplaceholder.typicode.com

So, when I hit [localhost:port/](http://localhost:3333/)myExpressRoutePath Express will match the route, use the middleware, and interestingly prepend the path to the proxied target.

[localhost:port/](http://localhost:3333/)myExpressRoutePathhttp://some.target.com/myExpressRoutePath

If I want the resultant target URL to not include the route path I need to use the prependPath:false option. By doing that any path will be discarded by the HPM.

So the routes would be controlled by the Express route matching.

CONTROL VIA PROXY

Another option to control when to proxy is by providing the context param to HPM. The simplest form of context is a path (regex for pattern matching and function are possible too). So if I invoke createProxyMiddleware function as

createProxyMiddleware('/api', {
    target: 'http://some.target.com',
    changeOrigin: true, // for virtual hosted sites, changes Host HTTP header to match to target's host and avoid "Direct IP access not allowed" errors
    logLevel: 'debug',
    logger: console
}) // matches paths starting with /api

Then when I point to localhost:port/api I will be proxied to http://some.target.com/api, otherwise proxy won’t occur.

If I point to localhost:port/api/whatever I would be redirected to http://some.target.com/api/whatever

Sometimes I want to use a path context that is not exactly like the target path.

For example

const jsonPlaceholderProxy = createProxyMiddleware('/got-api', {
  target: 'https://www.anapioficeandfire.com/api',
	ignorePath: true
});
app.use(jsonPlaceholderProxy);

Here I don’t want the got-api path to be propagated to the target, so ignorePath: *true* comes in handy. However, any other path will also be discarded.

That’s why is probably more useful to use path-rewrite. For example

pathRewrite: { 
	'^/got-api': '',
	'^/got-api/libros': '/books', 
	'^/got-api/casas': '/houses', 
	'^/got-api/personajes': '/characters'
},
2024. Personal website built with Astro & Streamline.