Skip to content

Commit

Permalink
Support for multiple domains.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Montes committed Mar 15, 2013
1 parent b019f2e commit 1c8e5a8
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 13 deletions.
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# express-subdomains
[![Build Status](https://secure.travis-ci.org/tblobaum/express-subdomains.png)](http://travis-ci.org/tblobaum/express-subdomains)
[![Build Status](https://secure.travis-ci.org/tblobaum/express-subdomains.png)](http://travis-ci.org/tblobaum/express-subdomains)

Subdomains are placed at the beginning of a route by default.

## Example
## Basic example

```javascript

Expand All @@ -17,7 +17,7 @@ subdomains
.use('api')
.use('other.vanity.domain');

// Place this line before
// Place this line before
// app.use(app.router)
app.use(subdomains.middleware);

Expand All @@ -27,9 +27,27 @@ app.get('/api/user' function (req, res, next) {
})

app.listen();

````

## API

### domain(url)

Set the domain url to be used in all the following calls to ```use```.
Can be set to "" to match any domains.

### use(base, options)

Set a subdomain as ```base```. If ```domain``` is set, it will be added
to the subdomian to form a full host url.

### strict()

By default, ```subdomains``` will not change the url when no rules
match. If only defined subdomain+domain matches are required,
```strict``` shall be called.

## Testing locally

Add the following line(s) to your /etc/hosts file
Expand Down
36 changes: 27 additions & 9 deletions lib/subdomains.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
* MIT Licensed
*/

var domain = "",
subs = [{ base: '.' }],
var domain,
subs,
Sequence = require('sequence');

module.exports = {
init: function () {
domain = "";
subs = [{ base: '.', options: {} }];
},
use: function (base, options) {
subs.unshift({
base: base,
domain: domain ? domain : "",
options: options || {}
});
return this;
Expand All @@ -20,21 +25,32 @@ module.exports = {
domain = url;
return this;
},
strict: function () {
subs.slice(-1)[0].options.strict = true;
return this;
},
middleware: function (req, res, next) {
forEachAsync(subs, function (fn, item, i, arr) {
var regexp = item.base;
if (regexp !== '.') { regexp = "^" + regexp + "\\."; }
if (domain) { regexp = regexp + domain + "(:[0-9]*)?$"; }
if (RegExp(regexp, "gi").test(req.headers.host)) {
if (item.base !== '.') {
if (item.base !== '.') {
var regexp = "^" + item.base + "\\.";
if (item.domain) {
regexp += item.domain.replace(".", "\\.") + "(:[0-9]*)?$";
}
if (RegExp(regexp, "gi").test(req.headers.host)) {
if (req.url === '/') {
req.url = '';
}
req.url = '/' + item.base + req.url;
next();
} else {
fn();
}
next();
} else {
fn();
if (!item.options.strict) {
next();
} else {
res.send(404);
}
}
});
}
Expand All @@ -50,3 +66,5 @@ function forEachAsync(arr, callback) {
arr.forEach(handleItem);
return sequence;
}

module.exports.init();
94 changes: 94 additions & 0 deletions test/subdomains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.use('api')
subdomains.middleware.apply({}, args)
})
Expand All @@ -30,6 +31,7 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.use('api.01.vanity')
subdomains.middleware.apply({}, args)
})
Expand All @@ -44,6 +46,7 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.use('api')
subdomains.middleware.apply({}, args)
})
Expand All @@ -58,6 +61,7 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.use('api')
subdomains.middleware.apply({}, args)
})
Expand All @@ -72,6 +76,7 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.use('api')
subdomains.middleware.apply({}, args)
})
Expand All @@ -86,6 +91,7 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.domain('domain.com').use('api')
subdomains.middleware.apply({}, args)
})
Expand All @@ -100,8 +106,96 @@ describe('express-subdomains', function () {
done()
}
]
subdomains.init();
subdomains.domain('domain.com').use('api')
subdomains.middleware.apply({}, args)
})

it('should not match "." within domain with different domain into a route', function (done) {
var req = { url: '/', headers: { host: 'api.otherxdomain.com' } },
args = [
req,
{},
function () {
assert.strictEqual(req.url, '/', 'route should be `/`')
done()
}
]
subdomains.init();
subdomains.domain('other.domain.com').use('api')
subdomains.middleware.apply({}, args)
})

it('should convert a subdomain and first domain into a route', function (done) {
var req = { url: '/', headers: { host: 'api.domain.com' } },
args = [
req,
{},
function () {
assert.strictEqual(req.url, '/api', 'route should be `/`')
done()
}
]
subdomains.init();
subdomains.domain('domain.com').use('api')
subdomains.domain('otherdomain.com').use('www')
subdomains.middleware.apply({}, args)
})

it('should convert a subdomain and last domain a route', function (done) {
var req = { url: '/', headers: { host: 'api.domain.com' } },
args = [
req,
{},
function () {
assert.strictEqual(req.url, '/api', 'route should be `/`')
done()
}
]
subdomains.init();
subdomains.domain('otherdomain.com').use('www')
subdomains.domain('domain.com').use('api')
subdomains.middleware.apply({}, args)
})

it('should bypass any non matching route', function (done) {
var req = { url: '/', headers: { host: 'api.domain.com' } },
args = [
req,
{
send: function (code) {
assert.strictEqual(code, 404, 'exit code should not be 404')
done()
}
},
function () {
assert.strictEqual(req.url, '/', 'route should be `/`')
done()
}
]
subdomains.init();
subdomains.domain('domain.com').use('api2')
subdomains.middleware.apply({}, args)
})

it('should not bypass any non matching route if strict is set', function (done) {
var req = { url: '/', headers: { host: 'api2.otherdomain.com' } },
args = [
req,
{
send: function (code) {
assert.strictEqual(code, 404, 'code should be 404')
done()
}
},
function () {
assert.fail(req.url, 'none', 'route should not match')
done()
}
]
subdomains.init();
subdomains.domain('otherdomain.com').use('api').strict()
subdomains.middleware.apply({}, args)
})

})

0 comments on commit 1c8e5a8

Please sign in to comment.