Skip to content

Commit 49abd7b

Browse files
committed
merge
2 parents 0ebebd8 + ab75fa0 commit 49abd7b

File tree

3 files changed

+231
-189
lines changed

3 files changed

+231
-189
lines changed

lib/response.js

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -588,56 +588,40 @@ res.cookie = function(name, val, options){
588588
return this;
589589
};
590590

591+
591592
/**
592-
* Redirect to the given `url` with optional response `status`
593-
* defaulting to 302.
593+
* Set the location header to `url`.
594594
*
595595
* The given `url` can also be the name of a mapped url, for
596596
* example by default express supports "back" which redirects
597597
* to the _Referrer_ or _Referer_ headers or "/".
598598
*
599599
* Examples:
600600
*
601-
* res.redirect('/foo/bar');
602-
* res.redirect('http://example.com');
603-
* res.redirect(301, 'http://example.com');
604-
* res.redirect('http://example.com', 301);
605-
* res.redirect('../login'); // /blog/post/1 -> /blog/login
601+
* res.location('/foo/bar').;
602+
* res.location('http://example.com');
603+
* res.location('../login'); // /blog/post/1 -> /blog/login
606604
*
607605
* Mounting:
608606
*
609-
* When an application is mounted, and `res.redirect()`
610-
* is given a path that does _not_ lead with "/". For
611-
* example suppose a "blog" app is mounted at "/blog",
612-
* the following redirect would result in "/blog/login":
607+
* When an application is mounted and `res.location()`
608+
* is given a path that does _not_ lead with "/" it becomes
609+
* relative to the mount-point. For example if the application
610+
* is mounted at "/blog", the following would become "/blog/login".
613611
*
614-
* res.redirect('login');
612+
* res.location('login');
615613
*
616-
* While the leading slash would result in a redirect to "/login":
614+
* While the leading slash would result in a location of "/login":
617615
*
618-
* res.redirect('/login');
616+
* res.location('/login');
619617
*
620618
* @param {String} url
621-
* @param {Number} code
622619
* @api public
623620
*/
624621

625-
res.redirect = function(url){
622+
res.location = function(url){
626623
var app = this.app
627-
, req = this.req
628-
, head = 'HEAD' == req.method
629-
, status = 302
630-
, body;
631-
632-
// allow status / url
633-
if (2 == arguments.length) {
634-
if ('number' == typeof url) {
635-
status = url;
636-
url = arguments[1];
637-
} else {
638-
status = arguments[1];
639-
}
640-
}
624+
, req = this.req;
641625

642626
// setup redirect map
643627
var map = { back: req.get('Referrer') || '/' };
@@ -658,6 +642,52 @@ res.redirect = function(url){
658642
}
659643
}
660644

645+
// Respond
646+
this.set('Location', url);
647+
return this;
648+
};
649+
650+
/**
651+
* Redirect to the given `url` with optional response `status`
652+
* defaulting to 302.
653+
*
654+
* The resulting `url` is determined by `res.location()`, so
655+
* it will play nicely with mounted apps, relative paths,
656+
* `"back"` etc.
657+
*
658+
* Examples:
659+
*
660+
* res.redirect('/foo/bar');
661+
* res.redirect('http://example.com');
662+
* res.redirect(301, 'http://example.com');
663+
* res.redirect('http://example.com', 301);
664+
* res.redirect('../login'); // /blog/post/1 -> /blog/login
665+
*
666+
* @param {String} url
667+
* @param {Number} code
668+
* @api public
669+
*/
670+
671+
res.redirect = function(url){
672+
var app = this.app
673+
, head = 'HEAD' == this.req.method
674+
, status = 302
675+
, body;
676+
677+
// allow status / url
678+
if (2 == arguments.length) {
679+
if ('number' == typeof url) {
680+
status = url;
681+
url = arguments[1];
682+
} else {
683+
status = arguments[1];
684+
}
685+
}
686+
687+
// Set location header
688+
this.location(url);
689+
url = this.get('Location');
690+
661691
// Support text/{plain,html} by default
662692
this.format({
663693
text: function(){
@@ -676,7 +706,6 @@ res.redirect = function(url){
676706

677707
// Respond
678708
this.statusCode = status;
679-
this.set('Location', url);
680709
this.set('Content-Length', Buffer.byteLength(body));
681710
this.end(head ? null : body);
682711
};

test/res.location.js

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
2+
var express = require('../')
3+
, request = require('./support/http');
4+
5+
describe('res', function(){
6+
describe('.location(url)', function(){
7+
it('should set the header', function(done){
8+
var app = express();
9+
10+
app.use(function(req, res){
11+
res.location('http://google.com').end();
12+
});
13+
14+
request(app)
15+
.get('/')
16+
.end(function(err, res){
17+
res.headers.should.have.property('location', 'http://google.com');
18+
done();
19+
})
20+
})
21+
22+
describe('with leading //', function(){
23+
it('should pass through scheme-relative urls', function(done){
24+
var app = express();
25+
26+
app.use(function(req, res){
27+
res.location('//cuteoverload.com').end();
28+
});
29+
30+
request(app)
31+
.get('/')
32+
.end(function(err, res){
33+
res.headers.should.have.property('location', '//cuteoverload.com');
34+
done();
35+
})
36+
})
37+
})
38+
39+
describe('with leading /', function(){
40+
it('should construct scheme-relative urls', function(done){
41+
var app = express();
42+
43+
app.use(function(req, res){
44+
res.location('/login').end();
45+
});
46+
47+
request(app)
48+
.get('/')
49+
.end(function(err, res){
50+
res.headers.should.have.property('location', '/login');
51+
done();
52+
})
53+
})
54+
})
55+
56+
describe('with leading ./', function(){
57+
it('should construct path-relative urls', function(done){
58+
var app = express();
59+
60+
app.use(function(req, res){
61+
res.location('./edit').end();
62+
});
63+
64+
request(app)
65+
.get('/post/1')
66+
.end(function(err, res){
67+
res.headers.should.have.property('location', '/post/1/./edit');
68+
done();
69+
})
70+
})
71+
})
72+
73+
describe('with leading ../', function(){
74+
it('should construct path-relative urls', function(done){
75+
var app = express();
76+
77+
app.use(function(req, res){
78+
res.location('../new').end();
79+
});
80+
81+
request(app)
82+
.get('/post/1')
83+
.end(function(err, res){
84+
res.headers.should.have.property('location', '/post/1/../new');
85+
done();
86+
})
87+
})
88+
})
89+
90+
describe('without leading /', function(){
91+
it('should construct mount-point relative urls', function(done){
92+
var app = express();
93+
94+
app.use(function(req, res){
95+
res.location('login').end();
96+
});
97+
98+
request(app)
99+
.get('/')
100+
.end(function(err, res){
101+
res.headers.should.have.property('location', '/login');
102+
done();
103+
})
104+
})
105+
})
106+
107+
describe('when mounted', function(){
108+
describe('deeply', function(){
109+
it('should respect the mount-point', function(done){
110+
var app = express()
111+
, blog = express()
112+
, admin = express();
113+
114+
admin.use(function(req, res){
115+
res.location('login').end();
116+
});
117+
118+
app.use('/blog', blog);
119+
blog.use('/admin', admin);
120+
121+
request(app)
122+
.get('/blog/admin')
123+
.end(function(err, res){
124+
res.headers.should.have.property('location', '/blog/admin/login');
125+
done();
126+
})
127+
})
128+
})
129+
130+
describe('omitting leading /', function(){
131+
it('should respect the mount-point', function(done){
132+
var app = express()
133+
, admin = express();
134+
135+
admin.use(function(req, res){
136+
res.location('admin/login').end();
137+
});
138+
139+
app.use('/blog', admin);
140+
141+
request(app)
142+
.get('/blog')
143+
.end(function(err, res){
144+
res.headers.should.have.property('location', '/blog/admin/login');
145+
done();
146+
})
147+
})
148+
})
149+
150+
describe('providing leading /', function(){
151+
it('should ignore mount-point', function(done){
152+
var app = express()
153+
, admin = express();
154+
155+
admin.use(function(req, res){
156+
res.location('/admin/login').end();
157+
});
158+
159+
app.use('/blog', admin);
160+
161+
request(app)
162+
.get('/blog')
163+
.end(function(err, res){
164+
res.headers.should.have.property('location', '/admin/login');
165+
done();
166+
})
167+
})
168+
})
169+
})
170+
})
171+
})

0 commit comments

Comments
 (0)