[Pkg-javascript-commits] [node-vhost] 01/02: Imported Upstream version 2.0.0

Leo Iannacone l3on-guest at moszumanska.debian.org
Sat Jun 14 16:16:10 UTC 2014


This is an automated email from the git hooks/post-receive script.

l3on-guest pushed a commit to branch master
in repository node-vhost.

commit 37d04cdb7307bbaf0a5b0d159528bab54f6c33bf
Author: Leo Iannacone <l3on at ubuntu.com>
Date:   Sat Jun 14 18:05:03 2014 +0200

    Imported Upstream version 2.0.0
---
 .npmignore   |   2 +
 .travis.yml  |  11 +++
 HISTORY.md   |  15 ++++
 README.md    | 137 ++++++++++++++++++++++++++++++++
 index.js     | 179 ++++++++++++++++++++++++++++++++++++++++++
 package.json |  25 ++++++
 test/test.js | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 621 insertions(+)

diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..fcf9ef9
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,2 @@
+coverage/
+test/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1ff243c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
+  - "0.11"
+matrix:
+  allow_failures:
+    - node_js: "0.11"
+  fast_finish: true
+script: "npm run-script test-travis"
+after_script: "npm install coveralls at 2.10.0 && cat ./coverage/lcov.info | coveralls"
diff --git a/HISTORY.md b/HISTORY.md
new file mode 100644
index 0000000..848399e
--- /dev/null
+++ b/HISTORY.md
@@ -0,0 +1,15 @@
+2.0.0 / 2014-06-08
+==================
+
+  * Accept `RegExp` object for `hostname`
+  * Provide `req.vhost` object
+  * Remove old invocation of `server.onvhost`
+  * String `hostname` with `*` behaves more like SSL certificates
+    - Matches 1 or more characters instead of zero
+    - No longer matches "." characters
+  * Support IPv6 literal in `Host` header
+
+1.0.0 / 2014-03-05
+==================
+
+  * Genesis from `connect`
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e238daf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,137 @@
+# vhost
+
+[![NPM version](https://badge.fury.io/js/vhost.svg)](http://badge.fury.io/js/vhost)
+[![Build Status](https://travis-ci.org/expressjs/vhost.svg?branch=master)](https://travis-ci.org/expressjs/vhost)
+[![Coverage Status](https://img.shields.io/coveralls/expressjs/vhost.svg?branch=master)](https://coveralls.io/r/expressjs/vhost)
+
+Previously `connect.vhost()`.
+
+## Install
+
+```sh
+$ npm install vhost
+```
+
+## API
+
+```js
+var vhost = require('vhost')
+```
+
+### vhost(hostname, server)
+
+Create a new middleware function to hand off request to `server` when the incoming
+host for the request matches `hostname`.
+
+`hostname` can be a string or a RegExp object. When `hostname` is a string it can
+contain `*` to match 1 or more characters in that section of the hostname. When
+`hostname` is a RegExp, it will be forced to case-insensitive (since hostnames are)
+and will be forced to match based on the start and end of the hostname.
+
+When host is matched and the request is sent down to a vhost handler, the `req.vhost`
+property will be populated with an object. This object will have numeric properties
+corresponding to each wildcard (or capture group if RegExp object provided) and the
+`hostname` that was matched.
+
+```js
+// for match of "foo.bar.example.com:8080" against "*.*.example.com":
+req.vhost.host === 'foo.bar.example.com:8080'
+req.vhost.hostname === 'foo.bar.example.com'
+req.vhost.length === 2
+req.vhost[0] === 'foo'
+req.vhost[1] === 'bar'
+```
+
+## Examples
+
+### using with connect for static serving
+
+```js
+var connect = require('connect')
+var serveStatic = require('serve-static')
+var vhost = require('vhost')
+
+var mailapp = connect()
+
+// add middlewares to mailapp for mail.example.com
+
+// create app to serve static files on subdomain
+var staticapp = connect()
+staticapp.use(serveStatic('public'))
+
+// create main app
+var app = connect()
+
+// add vhost routing to main app for mail
+app.use(vhost('mail.example.com', mailapp))
+
+// route static assets for "assets-*" subdomain to get
+// around max host connections limit on browsers
+app.use(vhost('assets-*.example.com', staticapp))
+
+// add middlewares and main usage to app
+
+app.listen(3000)
+```
+
+### using with connect for user subdomains
+
+```js
+var connect = require('connect')
+var serveStatic = require('serve-static')
+var vhost = require('vhost')
+
+var mainapp = connect()
+
+// add middlewares to mainapp for the main web site
+
+// create app that will server user content from public/{username}/
+var userapp = connect()
+
+userapp.user(function(req, res, next){
+  var username = req.vhost[0] // username is the "*"
+
+  // pretend request was for /{username}/* for file serving
+  req.originalUrl = req.url
+  req.url = '/' + username + req.url
+
+  next()
+})
+userapp.use(serveStatic('public'))
+
+// create main app
+var app = connect()
+
+// add vhost routing for main app
+app.use(vhost('userpages.local', mainapp))
+app.use(vhost('www.userpages.local', mainapp))
+
+// listen on all subdomains for user pages
+app.use(vhost('*.userpages.local', userapp)
+
+app.listen(3000)
+```
+
+## License
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Jonathan Ong me at jongleberry.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..60059e5
--- /dev/null
+++ b/index.js
@@ -0,0 +1,179 @@
+
+/*!
+ * vhost
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2014 Jonathan Ong
+ * MIT Licensed
+ */
+
+/**
+ * vhost:
+ *
+ *   Setup vhost for the given `hostname` and `server`.
+ *
+ *     connect()
+ *       .use(connect.vhost('foo.com', fooApp))
+ *       .use(connect.vhost('bar.com', barApp))
+ *       .use(connect.vhost('*.com', mainApp))
+ *
+ *  The `server` may be a Connect server, a callable function,
+ *  or a regular Node `http.Server`.
+ *
+ * @param {string|RegExp} hostname
+ * @param {function|Server} server
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function vhost(hostname, server){
+  if (!hostname) {
+    throw new TypeError('argument hostname is required')
+  }
+
+  if (!server) {
+    throw new Error('argument server is required')
+  }
+
+  // create a handle for the server
+  var handle = createHandle(server)
+
+  // 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)
+  };
+};
+
+/**
+ * Create handle to server.
+ *
+ * @param {function|Server} server
+ * @return {function}
+ * @api private
+ */
+
+function createHandle(server){
+  if (typeof server === 'function') {
+    // callable servers are the handle
+    return server
+  } else if (typeof server.emit === 'function') {
+    // emit request event on server
+    return function handle(req, res) {
+      server.emit('request', req, res)
+    }
+  }
+
+  throw new TypeError('argument server is unsupported')
+}
+
+/**
+ * Get hostname of request.
+ *
+ * @param (object} req
+ * @return {string}
+ * @api 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}
+ * @api private
+ */
+
+function isregexp(val){
+  return Object.prototype.toString.call(val) === '[object RegExp]'
+}
+
+/**
+ * Generate RegExp for given hostname value.
+ *
+ * @param (string|RegExp} val
+ * @api private
+ */
+
+function hostregexp(val){
+  var source = !isregexp(val)
+    ? String(val).replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1').replace(/\*/g, '([^\.]+)')
+    : val.source
+
+  // force leading anchor matching
+  if (source[0] !== '^') {
+    source = '^' + source
+  }
+
+  // force trailing anchor matching
+  source = source.replace(/(\\*)(.)$/, function(s, b, c){
+    return c !== '$' || b.length % 2 === 1
+      ? s + '$'
+      : s
+  })
+
+  return new RegExp(source, 'i')
+}
+
+/**
+ * Get the vhost data of the request for RegExp
+ *
+ * @param (object} req
+ * @param (RegExp} regexp
+ * @return {object}
+ * @api 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
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d293205
--- /dev/null
+++ b/package.json
@@ -0,0 +1,25 @@
+{
+  "name": "vhost",
+  "description": "virtual domain hosting",
+  "version": "2.0.0",
+  "author": "Jonathan Ong <me at jongleberry.com> (http://jongleberry.com)",
+  "contributors": [
+    "Douglas Christopher Wilson <doug at somethingdoug.com>"
+  ],
+  "license": "MIT",
+  "repository": "expressjs/vhost",
+  "devDependencies": {
+    "istanbul": "0.2.10",
+    "mocha": "~1.20.1",
+    "should": "~4.0.1",
+    "supertest": "~0.13.0"
+  },
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "mocha --reporter dot test/",
+    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/",
+    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/"
+  }
+}
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..779606f
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,252 @@
+
+var http = require('http')
+var request = require('supertest')
+var should = require('should')
+var vhost = require('..')
+
+describe('vhost(hostname, server)', function(){
+  it('should route by Host', function(done){
+    var vhosts = []
+
+    vhosts.push(vhost('tobi.com', tobi))
+    vhosts.push(vhost('loki.com', loki))
+
+    var app = createServer(vhosts)
+
+    function tobi(req, res) { res.end('tobi') }
+    function loki(req, res) { res.end('loki') }
+
+    request(app)
+    .get('/')
+    .set('Host', 'tobi.com')
+    .expect(200, 'tobi', done)
+  })
+
+  it('should ignore port in Host', function(done){
+    var app = createServer('tobi.com', function (req, res) {
+      res.end('tobi')
+    })
+
+    request(app)
+    .get('/')
+    .set('Host', 'tobi.com:8080')
+    .expect(200, 'tobi', done)
+  })
+
+  it('should support IPv6 literal in Host', function(done){
+    var app = createServer('[::1]', function (req, res) {
+      res.end('loopback')
+    })
+
+    request(app)
+    .get('/')
+    .set('Host', '[::1]:8080')
+    .expect(200, 'loopback', done)
+  })
+
+  it('should 404 unless matched', function(done){
+    var vhosts = []
+
+    vhosts.push(vhost('tobi.com', tobi))
+    vhosts.push(vhost('loki.com', loki))
+
+    var app = createServer(vhosts)
+
+    function tobi(req, res) { res.end('tobi') }
+    function loki(req, res) { res.end('loki') }
+
+    request(app.listen())
+    .get('/')
+    .set('Host', 'ferrets.com')
+    .expect(404, done)
+  })
+
+  it('should 404 without Host header', function(done){
+    var vhosts = []
+
+    vhosts.push(vhost('tobi.com', tobi))
+    vhosts.push(vhost('loki.com', loki))
+
+    var app = createServer(vhosts)
+
+    function tobi(req, res) { res.end('tobi') }
+    function loki(req, res) { res.end('loki') }
+
+    request(app.listen())
+    .get('/')
+    .unset('Host')
+    .expect(404, done)
+  })
+
+  describe('arguments', function(){
+    describe('hostname', function(){
+      it('should be required', function(){
+        vhost.bind().should.throw(/hostname.*required/)
+      })
+
+      it('should accept string', function(){
+        vhost.bind(null, 'loki.com', function(){}).should.not.throw()
+      })
+
+      it('should accept RegExp', function(){
+        vhost.bind(null, /loki\.com/, function(){}).should.not.throw()
+      })
+    })
+
+    describe('server', function(){
+      it('should be required', function(){
+        vhost.bind(null, 'loki.com').should.throw(/server.*required/)
+      })
+
+      it('should accept function', function(){
+        vhost.bind(null, 'loki.com', function(){}).should.not.throw()
+      })
+
+      it('should accept http server', function(){
+        vhost.bind(null, 'loki.com', http.createServer()).should.not.throw()
+      })
+
+      it('should reject plain object', function(){
+        vhost.bind(null, 'loki.com', {}).should.throw(/server.*unsupported/)
+      })
+    })
+  })
+
+  describe('with string hostname', function(){
+    it('should support wildcards', function(done){
+      var app = createServer('*.ferrets.com', function(req, res){
+        res.end('wildcard!')
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'loki.ferrets.com')
+      .expect(200, 'wildcard!', done)
+    })
+
+    it('should restrict wildcards to single part', function(done){
+      var app = createServer('*.ferrets.com', function(req, res){
+        res.end('wildcard!')
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'foo.loki.ferrets.com')
+      .expect(404, done)
+    })
+
+    it('should treat dot as a dot', function(done){
+      var app = createServer('a.b.com', function(req, res){
+        res.end('tobi')
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'aXb.com')
+      .expect(404, done)
+    })
+
+    it('should match entire string', function(done){
+      var app = createServer('.com', function(req, res){
+        res.end('commercial')
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'foo.com')
+      .expect(404, done)
+    })
+
+    it('should populate req.vhost', function(done){
+      var app = createServer('user-*.*.com', function(req, res){
+        var keys = Object.keys(req.vhost).sort()
+        var arr = keys.map(function(k){ return [k, req.vhost[k]] })
+        res.end(JSON.stringify(arr))
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'user-bob.foo.com:8080')
+      .expect(200, '[["0","bob"],["1","foo"],["host","user-bob.foo.com:8080"],["hostname","user-bob.foo.com"],["length",2]]', done)
+    })
+  })
+
+  describe('with RegExp hostname', function(){
+    it('should match using RegExp', function(done){
+      var app = createServer(/[tl]o[bk]i\.com/, function(req, res){
+        res.end('tobi')
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'toki.com')
+      .expect(200, 'tobi', done)
+    })
+
+    it('should match entire hostname', function(done){
+      var vhosts = []
+
+      vhosts.push(vhost(/\.tobi$/, tobi))
+      vhosts.push(vhost(/^loki\./, loki))
+
+      var app = createServer(vhosts)
+
+      function tobi(req, res) { res.end('tobi') }
+      function loki(req, res) { res.end('loki') }
+
+      request(app)
+      .get('/')
+      .set('Host', 'loki.tobi.com')
+      .expect(404, done)
+    })
+
+    it('should populate req.vhost', function(done){
+      var app = createServer(/user-(bob|joe)\.([^\.]+)\.com/, function(req, res){
+        var keys = Object.keys(req.vhost).sort()
+        var arr = keys.map(function(k){ return [k, req.vhost[k]] })
+        res.end(JSON.stringify(arr))
+      })
+
+      request(app)
+      .get('/')
+      .set('Host', 'user-bob.foo.com:8080')
+      .expect(200, '[["0","bob"],["1","foo"],["host","user-bob.foo.com:8080"],["hostname","user-bob.foo.com"],["length",2]]', done)
+    })
+  })
+
+  describe('server', function(){
+    it('should support http.Servers', function(done){
+      var loki = http.createServer(function(req, res){ res.end('loki') })
+      var app = createServer('loki.com', loki)
+
+      request(app)
+      .get('/')
+      .set('Host', 'loki.com')
+      .expect('loki', done)
+    })
+  })
+})
+
+function createServer(hostname, server) {
+  var vhosts = !Array.isArray(hostname)
+    ? [vhost(hostname, server)]
+    : hostname
+
+  return http.createServer(function onRequest(req, res) {
+    var index = 0
+
+    function next(err) {
+      var vhost = vhosts[index++]
+
+      if (!vhost || err) {
+        res.statusCode = err ? (err.status || 500) : 404
+        res.end(err ? err.message : 'oops')
+        return
+      }
+
+      vhost(req, res, next)
+    }
+
+    next()
+  })
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-vhost.git



More information about the Pkg-javascript-commits mailing list