Skip to content

Commit ab7b5f7

Browse files
Redirect protocol and host (#150)
Add support for redirecting the protocol and host
1 parent db677db commit ab7b5f7

File tree

6 files changed

+97
-41
lines changed

6 files changed

+97
-41
lines changed

circle.yml

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
machine:
22
node:
3-
version: v4.5.0
4-
dependencies:
5-
# https://discuss.circleci.com/t/testing-multiple-versions-of-node/542
6-
pre:
7-
- case $CIRCLE_NODE_INDEX in 0) NODE_VERSION=0.12 ;; 1) NODE_VERSION=4 ;; esac; nvm install $NODE_VERSION && nvm alias default $NODE_VERSION
3+
version: v4.8.4
4+
npm:
5+
version: v2.15.11

lib/redirect.js

+37-34
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,58 @@ var moment = require('moment');
77

88
var utils = require('./utils.js');
99

10-
var Redirect = function( redirect_data, options ){
11-
10+
var Redirect = function(redirect_data, options) {
1211
options = options || {};
1312

1413
var redirect = this;
15-
var server = options.server;
16-
var router = server.router;
14+
var router = options.server.router;
1715
var status = redirect_data.permanent ? PERMANENT_STATUS : TEMPORARY_STATUS;
1816
var start = redirect_data.start;
1917
var end = redirect_data.end;
20-
var from = redirect_data.from;
21-
var to = redirect_data.to;
22-
var expired = ( moment() > moment( end ) );
23-
24-
// don't create redirect route at all if expired
25-
// don't check prematurity yet since it could become valid later
26-
if( !expired ){
27-
28-
if (from instanceof RegExp) {
29-
this.route = from;
30-
} else {
31-
this.route = path.normalize( from ).replace( /\\/g, '/' );
32-
this.route = utils.formatRouteForExpress(this.route);
18+
var from = _.isObject(redirect_data.from) && !_.isRegExp(redirect_data.from) ? redirect_data.from : {path: redirect_data.from};
19+
var to = _.isObject(redirect_data.to) && !_.isFunction(redirect_data.to) ? redirect_data.to : {url: redirect_data.to};
20+
var expired = moment() > moment(end);
21+
22+
// Don't create redirect route at all if expired
23+
// Don't check prematurity yet since it could become valid later
24+
if (!expired) {
25+
redirect.route = from.path || '*';
26+
if (_.isString(redirect.route)) {
27+
redirect.route = path.normalize(redirect.route).replace(/\\/g, '/');
28+
redirect.route = utils.formatRouteForExpress(redirect.route);
3329
}
3430

35-
router.get( this.route, function( req, res, next ){
36-
var expired = ( moment() > moment( end ) );
37-
var premature = ( moment() < moment( start ) );
38-
// if redirect is expired or premature skip it
39-
if( !expired && !premature ){
40-
var url = typeof(to) == 'function' ? to(req.params) : to;
41-
res.redirect( status, utils.expandVariables(url, req.params) );
42-
}
43-
else {
44-
next();
31+
router.get(redirect.route, function(req, res, next) {
32+
// If redirect is expired or premature skip it
33+
var expired = moment() > moment(end);
34+
var premature = moment() < moment(start);
35+
if (expired || premature) return next();
36+
37+
// If the protocol or host don't match, skip redirect
38+
if (from.protocol && from.protocol !== req.protocol) return next();
39+
if (from.host && from.host !== req.host) return next();
40+
41+
// Compute to
42+
var newTo = to;
43+
if (_.isFunction(newTo.url)) {
44+
newTo = newTo.url(req.params);
45+
if (!_.isObject(newTo)) newTo = Object.assign({}, to, {url: newTo});
4546
}
46-
});
4747

48-
// removes the redirect route
49-
this.destroy = function(){
48+
// Compute location
49+
var location = newTo.protocol || newTo.host ? ((newTo.protocol || req.protocol) + '://' + (newTo.host || req.host)) : '';
50+
location += newTo.url ? utils.expandVariables(newTo.url, req.params) : req.url;
5051

51-
router.routes.get = _( router.routes.get ).reject( function( current_route ){
52+
res.redirect(status, location);
53+
});
54+
55+
// Removes the redirect route
56+
this.destroy = function() {
57+
router.routes.get = _(router.routes.get).reject(function(current_route) {
5258
return redirect.route === current_route.path;
5359
});
54-
5560
};
56-
5761
}
58-
5962
};
6063

6164
module.exports = Redirect;

lib/server.js

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ var SolidusServer = function( options ){
116116
router.engine( DEFAULT_VIEW_EXTENSION, handlebars.engine );
117117
router.set( 'view engine', DEFAULT_VIEW_EXTENSION );
118118
router.set( 'views', paths.views );
119+
router.set( 'trust proxy', true ); // Use the X-Forwarded-* headers: https://expressjs.com/en/guide/behind-proxies.html
119120
router.use( express.compress() );
120121
router.use(function(req, res, next) {
121122
res.set({'X-Powered-By': 'Solidus/' + VERSION});

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"commander": "1.1.x",
2424
"continuation-local-storage": "~3.1.1",
2525
"express": "3.1.x",
26-
"express-expose": "SparkartGroupInc/express-expose#escape-script-ending-tag",
26+
"express-expose": "sparkartgroup/express-expose#escape-script-ending-tag",
2727
"express-handlebars": "1.2.2",
2828
"glob": "~3.2.6",
2929
"handlebars": "^1.3.0",

test/fixtures/site 1/redirects.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,38 @@ module.exports = [
3434
to: function(params) {
3535
return "/new/{1}/{0}/" + (1000 + parseInt(params['2']));
3636
}
37-
}];
37+
}, {
38+
from: {
39+
protocol: 'http',
40+
host: 'solidusjs.com',
41+
path: '/match-http-root'
42+
},
43+
to: '/new/match-http-root'
44+
}, {
45+
from: {
46+
protocol: 'https',
47+
host: 'solidusjs.com',
48+
path: '/match-https-root'
49+
},
50+
to: '/new/match-https-root'
51+
}, {
52+
from: {
53+
host: 'no-path.com'
54+
},
55+
to: {
56+
host: 'www.no-path.com'
57+
}
58+
}, {
59+
from: '/to-https-www',
60+
to: {
61+
protocol: 'https',
62+
host: 'www.solidusjs.com'
63+
}
64+
}, {
65+
from: '/to-https-www-url/{dynamic}',
66+
to: {
67+
protocol: 'https',
68+
host: 'www.solidusjs.com',
69+
url: '/new/url/{dynamic}'
70+
}
71+
}];

test/solidus.js

+20
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,26 @@ describe( 'Solidus', function(){
583583
function( callback ){
584584
s_request.get('/redirect9/12-34-56-78').expect( 'location', '/new/56/12/1078', callback );
585585
},
586+
function( callback ){
587+
s_request.get('/match-http-root?with=params').set('Host', 'solidusjs.com').expect( 'location', '/new/match-http-root', callback );
588+
},
589+
function( callback ){
590+
// Bad protocol
591+
s_request.get('/match-https-root?with=params').set('Host', 'solidusjs.com').expect( 404, callback );
592+
},
593+
function( callback ){
594+
// Bad host
595+
s_request.get('/match-http-root?with=params').set('Host', 'www.solidusjs.com').expect( 404, callback );
596+
},
597+
function( callback ){
598+
s_request.get('/some/path?with=params').set('Host', 'no-path.com').expect( 'location', 'http://www.no-path.com/some/path?with=params', callback );
599+
},
600+
function( callback ){
601+
s_request.get('/to-https-www?with=params').set('Host', 'solidusjs.com').expect( 'location', 'https://www.solidusjs.com/to-https-www?with=params', callback );
602+
},
603+
function( callback ){
604+
s_request.get('/to-https-www-url/old-path?with=params').set('Host', 'solidusjs.com').expect( 'location', 'https://www.solidusjs.com/new/url/old-path', callback );
605+
},
586606
function( callback ){
587607
s_request.get('/past-redirect').expect( 404, callback );
588608
},

0 commit comments

Comments
 (0)