Skip to content

Instantly share code, notes, and snippets.

@ierceg
Created January 10, 2014 11:46
Show Gist options
  • Save ierceg/8350612 to your computer and use it in GitHub Desktop.
Save ierceg/8350612 to your computer and use it in GitHub Desktop.
Virtual route, resource and subdomain middleware for Connect, based on connect.vhost. I'll make it a real (documented, commented, tested) module when I get some time. I use it on Heroku to have several express instances all connected together on a single dyno. It allows me to modularize the system but using just one dyno and not web + workers du…
// All these functions are literally based on connect.vhost which borders on unintelligible. I'll fix that when converting to module.
exports.vroute = function(route, server) {
if (!route) throw new Error('vroute route required');
if (!server) throw new Error('vroute server required');
var regexpString = '^\\/' + cleanForRegexp(route) + '(\\/.*)$';
var regexp = new RegExp(regexpString, 'i');
return function(req, res, next) {
if(!req || !req.url) return next();
var matches = req.url.match(regexp);
if(!matches || matches.length <= 1 || !matches[1]) return next();
req.url = matches[1];
if('function' == typeof server) return server(req, res, next);
server.emit('request', req, res);
}
}
exports.vresource = function(path, server) {
if (!path) throw new Error('vresource path required');
if (!server) throw new Error('vresource server required');
var regexpString = '^\\/' + cleanForRegexp(path) + '\\/.*$';
var regexp = new RegExp(regexpString, 'i');
return function(req, res, next) {
if(!req || !req.url) return next();
if(!regexp.test(req.url)) return next();
if('function' == typeof server) return server(req, res, next);
server.emit('request', req, res);
}
}
exports.vsubdomain = function(subdomain, server) {
if (!subdomain) throw new Error('vsubdomain subdomain required');
if (!server) throw new Error('vsubdomain server required');
var regexpString = '^' + cleanForRegexp(subdomain) + '\\..+$';
var regexp = new RegExp(regexpString, 'i');
return function(req, res, next) {
if(!req || !req.headers || !req.headers.host) return next();
if(!regexp.test(req.headers.host)) return next();
if('function' == typeof server) return server(req, res, next);
server.emit('request', req, res);
}
}
var cleanForRegexp = function(raw) {
return raw.replace(/[^*\w]/g, '\\$&').replace(/[*]/g, '(?:.*?');
}
// Usage:
connect()
.use(vpath('api', api)) // will send all <your domain>/api to api server removing /api from req.url
.use(vresource('api', api)) // will send all <your domain>/api to api server without removing /api from req.url
.use(vsubdomain('api', api)) // will send all api.<your domain> to api server
.use(frontend) // all requests that weren't sent to api will end up here
.listen(process.env.PORT || 12345);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment