165 lines
2.7 KiB
JavaScript
165 lines
2.7 KiB
JavaScript
|
/*!
|
||
|
* vhost
|
||
|
* Copyright(c) 2014 Jonathan Ong
|
||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||
|
* MIT Licensed
|
||
|
*/
|
||
|
|
||
|
'use strict'
|
||
|
|
||
|
/**
|
||
|
* Module exports.
|
||
|
* @public
|
||
|
*/
|
||
|
|
||
|
module.exports = vhost
|
||
|
|
||
|
/**
|
||
|
* Module variables.
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
var asteriskRegExp = /\*/g
|
||
|
var asteriskReplace = '([^\.]+)'
|
||
|
var endAnchoredRegExp = /(?:^|[^\\])(?:\\\\)*\$$/
|
||
|
var escapeRegExp = /([.+?^=!:${}()|\[\]\/\\])/g
|
||
|
var escapeReplace = '\\$1'
|
||
|
|
||
|
/**
|
||
|
* Create a vhost middleware.
|
||
|
*
|
||
|
* @param {string|RegExp} hostname
|
||
|
* @param {function} handle
|
||
|
* @return {Function}
|
||
|
* @public
|
||
|
*/
|
||
|
|
||
|
function vhost(hostname, handle) {
|
||
|
if (!hostname) {
|
||
|
throw new TypeError('argument hostname is required')
|
||
|
}
|
||
|
|
||
|
if (!handle) {
|
||
|
throw new TypeError('argument handle is required')
|
||
|
}
|
||
|
|
||
|
if (typeof handle !== 'function') {
|
||
|
throw new TypeError('argument handle must be a function')
|
||
|
}
|
||
|
|
||
|
// create regular expression for hostname
|
||
|
var regexp = hostregexp(hostname)
|
||
|
|
||
|
return function vhost(req, res, next) {
|
||
|
var vhostdata = vhostof(req, regexp)
|
||
|
|
||
|
if (!vhostdata) {
|
||
|
return next()
|
||
|
}
|
||
|
|
||
|
// populate
|
||
|
req.vhost = vhostdata
|
||
|
|
||
|
// handle
|
||
|
handle(req, res, next)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get hostname of request.
|
||
|
*
|
||
|
* @param (object} req
|
||
|
* @return {string}
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
function hostnameof(req) {
|
||
|
var host = req.headers.host
|
||
|
|
||
|
if (!host) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var offset = host[0] === '['
|
||
|
? host.indexOf(']') + 1
|
||
|
: 0
|
||
|
var index = host.indexOf(':', offset)
|
||
|
|
||
|
return index !== -1
|
||
|
? host.substring(0, index)
|
||
|
: host
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determine if object is RegExp.
|
||
|
*
|
||
|
* @param (object} val
|
||
|
* @return {boolean}
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
function isregexp(val) {
|
||
|
return Object.prototype.toString.call(val) === '[object RegExp]'
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate RegExp for given hostname value.
|
||
|
*
|
||
|
* @param (string|RegExp} val
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
function hostregexp(val) {
|
||
|
var source = !isregexp(val)
|
||
|
? String(val).replace(escapeRegExp, escapeReplace).replace(asteriskRegExp, asteriskReplace)
|
||
|
: val.source
|
||
|
|
||
|
// force leading anchor matching
|
||
|
if (source[0] !== '^') {
|
||
|
source = '^' + source
|
||
|
}
|
||
|
|
||
|
// force trailing anchor matching
|
||
|
if (!endAnchoredRegExp.test(source)) {
|
||
|
source += '$'
|
||
|
}
|
||
|
|
||
|
return new RegExp(source, 'i')
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the vhost data of the request for RegExp
|
||
|
*
|
||
|
* @param (object} req
|
||
|
* @param (RegExp} regexp
|
||
|
* @return {object}
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
function vhostof(req, regexp) {
|
||
|
var host = req.headers.host
|
||
|
var hostname = hostnameof(req)
|
||
|
|
||
|
if (!hostname) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var match = regexp.exec(hostname)
|
||
|
|
||
|
if (!match) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var obj = Object.create(null)
|
||
|
|
||
|
obj.host = host
|
||
|
obj.hostname = hostname
|
||
|
obj.length = match.length - 1
|
||
|
|
||
|
for (var i = 1; i < match.length; i++) {
|
||
|
obj[i - 1] = match[i]
|
||
|
}
|
||
|
|
||
|
return obj
|
||
|
}
|