Skip to content

Instantly share code, notes, and snippets.

@steadicat
Created March 29, 2011 18:46
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save steadicat/892978 to your computer and use it in GitHub Desktop.
Save steadicat/892978 to your computer and use it in GitHub Desktop.
A reverse-proxy for CouchDB written in Node.js
#!/usr/local/bin/node
var sys = require('sys');
var http = require('http');
var url = require('url');
var PREFIX = '/db/';
var TARGET = 'http://example.cloudant.com';
var PORT = 8001;
function error(response, error, reason, code) {
sys.log('Error '+code+': '+error+' ('+reason+').');
response.writeHead(code, { 'Content-Type': 'application/json' });
response.write(JSON.stringify({ error: error, reason: reason }));
response.end();
}
function unknownError(response, e) {
sys.log(e.stack);
error(response, 'unknown', 'Unexpected error.', 500);
}
function forwardRequest(inRequest, inResponse, uri) {
sys.log(inRequest.method + ' ' + uri);
uri = url.parse(uri);
var out = http.createClient(uri.port||80, uri.hostname);
var path = uri.pathname + (uri.search || '');
var headers = inRequest.headers;
headers['host'] = uri.hostname + ':' + (uri.port||80);
headers['x-forwarded-for'] = inRequest.connection.remoteAddress;
headers['referer'] = 'http://' + uri.hostname + ':' + (uri.port||80) + '/';
var outRequest = out.request(inRequest.method, path, headers);
out.on('error', function(e) { unknownError(inResponse, e) });
outRequest.on('error', function(e) { unknownError(inResponse, e) });
inRequest.on('data', function(chunk) { outRequest.write(chunk) });
inRequest.on('end', function() {
outRequest.on('response', function(outResponse) {
// nginx does not support chunked transfers for proxied requests
delete outResponse.headers['transfer-encoding'];
if (outResponse.statusCode == 503) {
return error(inResponse, 'db_unavailable', 'Database server not available.', 502);
}
inResponse.writeHead(outResponse.statusCode, outResponse.headers);
outResponse.on('data', function(chunk) { inResponse.write(chunk); });
outResponse.on('end', function() { inResponse.end(); });
});
outRequest.end();
});
};
function handleRequest(request, response) {
var u = url.parse(request.url);
// Only serve URLs that start with PREFIX
if (u.pathname.substring(0, PREFIX.length) != PREFIX) return error(response, 'not_found', 'Nothing found here.', 404);
u = TARGET + u.pathname.substring(PREFIX.length-1) + (u.search||'');
forwardRequest(request, response, u);
}
process.on('uncaughtException', function(e) {
sys.log(e.stack);
});
http.createServer(handleRequest).listen(PORT);
sys.puts('Proxy ready on port '+PORT+'.')
@lancecarlson
Copy link

why not use http-proxy?

@mindvox
Copy link

mindvox commented Feb 16, 2017

An example using http-proxy as suggested by @lancecarlson.

var http = require('http');
var httpProxy = require('http-proxy');

var PROXY_TARGET = 'http://localhost:5984';
var PORT = 3000;

var proxy = httpProxy.createProxyServer({});
var server = http.createServer(function(request, response) {
  // here you can insert some custom logic to process `request` or `response`
  proxy.web(request, response, {
    target: PROXY_TARGET
  });
});

console.log('Listening on port %s', PORT);
server.listen(PORT);

Requests to http://localhost:3000 are proxied to CouchDB running on http://localhost:5984.

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