Skip to content

Instantly share code, notes, and snippets.

@jeffwhelpley
Last active July 21, 2022 12:07
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jeffwhelpley/5417758 to your computer and use it in GitHub Desktop.
Save jeffwhelpley/5417758 to your computer and use it in GitHub Desktop.
Getting node.js http-proxy to play nice with restify. This will also work for http-proxy with express or another node.js server. Note that I took various snippets of my code for this gist in order to try and convey the general idea. It won't work to just run this file.
/*
I have an existing node.js API server that runs on top of restify. I wanted to add http-proxy to forward
some calls to another API server. From the http-proxy examples out there, it seemed simply enough:
*/
var httpProxy = require('http-proxy');
var proxy = new httpProxy.RoutingProxy();
var restify = require('restify');
var server = restify.createServer();
server.get('/foo/:bar', function(req, res) {
proxy.proxyRequest(req, res, {
host: 'somehost.com',
port: 80
});
});
/*
But there is one pretty big reason why this didn't work for me. Later on in the code I have some restify middleware code:
*/
server.use(restify.acceptParser(server.acceptable));
server.use(restify.authorizationParser());
server.use(restify.queryParser());
server.use(restify.bodyParser({ mapParams: false }));
server.use(restify.gzipResponse());
/*
The reason this causes a problem is that the middleware calls are modifying the request object
in a way that prevents the ability of http-proxy to forward the request. In order for the proxy
to work, we can't mess with the request too much. I still needed this middleware for my existing
non-proxy API calls, so I created the following wrapper to conditionally implement each middleware:
*/
var wrapper = function(middleware) {
return function(req, res, next) {
var regex = /^\/foo.*$/;
// if url is a proxy request, don't do anything and move to next middleware
if(regex.test(req.url)) {
next();
}
// else invoke middleware
else {
// some middleware is an array (ex. bodyParser)
if(middleware instanceof Array) {
middleware[0](req, res, function() {
middleware[1](req, res, next);
});
}
else {
middleware(req, res, next);
}
}
};
};
// then I wrap my middleware calls with this function:
server.use(wrapper(restify.acceptParser(server.acceptable)));
server.use(wrapper(restify.authorizationParser()));
server.use(wrapper(restify.queryParser()));
server.use(wrapper(restify.bodyParser({ mapParams: false })));
server.use(wrapper(restify.gzipResponse()));
/*
I will eventually make the wrapper function more generic and robust to handle other potential situations,
but I think you get the gist.
*/
@leoh
Copy link

leoh commented Mar 30, 2014

Very helpful, thank you!

@joelosx
Copy link

joelosx commented Oct 6, 2014

jeff - any updates on this technique ?

Copy link

ghost commented Mar 2, 2015

I've used this gist. Very helpful, thanks.

@antklim
Copy link

antklim commented May 2, 2015

Very helpful, thank you!

@catamphetamine
Copy link

Webpack dev server now supports "proxy" parameter upon launch from javascript.
It works for me now.

@hartzis
Copy link

hartzis commented Nov 16, 2018

Just introduced a proxy to a restify service and initially attempted this pattern but felt it was too intrusive.
We discovered server.pre() from restify/pre which runs before all middleware and used it to setup a proxy.

Implemented this pattern and created a gist: https://gist.github.com/hartzis/ce191533d8579afe2481ddd5e2c6024a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment