fix(deps)!: mime-types@^3.0.0 (#5882)
[express.git] / test / res.location.js
blobc80b38de6b8f64b6478ee2a0abbb3ad2bdf2801b
1 'use strict'
3 var express = require('../')
4 , request = require('supertest')
5 , assert = require('assert')
6 , url = require('url');
8 describe('res', function(){
9 describe('.location(url)', function(){
10 it('should set the header', function(done){
11 var app = express();
13 app.use(function(req, res){
14 res.location('http://google.com/').end();
15 });
17 request(app)
18 .get('/')
19 .expect('Location', 'http://google.com/')
20 .expect(200, done)
23 it('should preserve trailing slashes when not present', function(done){
24 var app = express();
26 app.use(function(req, res){
27 res.location('http://google.com').end();
28 });
30 request(app)
31 .get('/')
32 .expect('Location', 'http://google.com')
33 .expect(200, done)
36 it('should encode "url"', function (done) {
37 var app = express()
39 app.use(function (req, res) {
40 res.location('https://google.com?q=\u2603 ยง10').end()
43 request(app)
44 .get('/')
45 .expect('Location', 'https://google.com?q=%E2%98%83%20%C2%A710')
46 .expect(200, done)
49 describe('when url is "back"', function () {
50 it('should set location from "Referer" header', function (done) {
51 var app = express()
53 app.use(function (req, res) {
54 res.location('back').end()
57 request(app)
58 .get('/')
59 .set('Referer', '/some/page.html')
60 .expect('Location', '/some/page.html')
61 .expect(200, done)
64 it('should set location from "Referrer" header', function (done) {
65 var app = express()
67 app.use(function (req, res) {
68 res.location('back').end()
71 request(app)
72 .get('/')
73 .set('Referrer', '/some/page.html')
74 .expect('Location', '/some/page.html')
75 .expect(200, done)
78 it('should prefer "Referrer" header', function (done) {
79 var app = express()
81 app.use(function (req, res) {
82 res.location('back').end()
85 request(app)
86 .get('/')
87 .set('Referer', '/some/page1.html')
88 .set('Referrer', '/some/page2.html')
89 .expect('Location', '/some/page2.html')
90 .expect(200, done)
93 it('should set the header to "/" without referrer', function (done) {
94 var app = express()
96 app.use(function (req, res) {
97 res.location('back').end()
100 request(app)
101 .get('/')
102 .expect('Location', '/')
103 .expect(200, done)
107 it('should encode data uri', function (done) {
108 var app = express()
109 app.use(function (req, res) {
110 res.location('data:text/javascript,export default () => { }').end();
113 request(app)
114 .get('/')
115 .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D')
116 .expect(200, done)
119 it('should encode data uri', function (done) {
120 var app = express()
121 app.use(function (req, res) {
122 res.location('data:text/javascript,export default () => { }').end();
125 request(app)
126 .get('/')
127 .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D')
128 .expect(200, done)
131 it('should consistently handle non-string input: boolean', function (done) {
132 var app = express()
133 app.use(function (req, res) {
134 res.location(true).end();
137 request(app)
138 .get('/')
139 .expect('Location', 'true')
140 .expect(200, done)
143 it('should consistently handle non-string inputs: object', function (done) {
144 var app = express()
145 app.use(function (req, res) {
146 res.location({}).end();
149 request(app)
150 .get('/')
151 .expect('Location', '[object%20Object]')
152 .expect(200, done)
155 it('should consistently handle non-string inputs: array', function (done) {
156 var app = express()
157 app.use(function (req, res) {
158 res.location([]).end();
161 request(app)
162 .get('/')
163 .expect('Location', '')
164 .expect(200, done)
167 it('should consistently handle empty string input', function (done) {
168 var app = express()
169 app.use(function (req, res) {
170 res.location('').end();
173 request(app)
174 .get('/')
175 .expect('Location', '')
176 .expect(200, done)
180 if (typeof URL !== 'undefined') {
181 it('should accept an instance of URL', function (done) {
182 var app = express();
184 app.use(function(req, res){
185 res.location(new URL('http://google.com/')).end();
188 request(app)
189 .get('/')
190 .expect('Location', 'http://google.com/')
191 .expect(200, done);
196 describe('location header encoding', function() {
197 function createRedirectServerForDomain (domain) {
198 var app = express();
199 app.use(function (req, res) {
200 var host = url.parse(req.query.q, false, true).host;
201 // This is here to show a basic check one might do which
202 // would pass but then the location header would still be bad
203 if (host !== domain) {
204 res.status(400).end('Bad host: ' + host + ' !== ' + domain);
206 res.location(req.query.q).end();
208 return app;
211 function testRequestedRedirect (app, inputUrl, expected, expectedHost, done) {
212 return request(app)
213 // Encode uri because old supertest does not and is required
214 // to test older node versions. New supertest doesn't re-encode
215 // so this works in both.
216 .get('/?q=' + encodeURIComponent(inputUrl))
217 .expect('') // No body.
218 .expect(200)
219 .expect('Location', expected)
220 .end(function (err, res) {
221 if (err) {
222 console.log('headers:', res.headers)
223 console.error('error', res.error, err);
224 return done(err, res);
227 // Parse the hosts from the input URL and the Location header
228 var inputHost = url.parse(inputUrl, false, true).host;
229 var locationHost = url.parse(res.headers['location'], false, true).host;
231 assert.strictEqual(locationHost, expectedHost);
233 // Assert that the hosts are the same
234 if (inputHost !== locationHost) {
235 return done(new Error('Hosts do not match: ' + inputHost + " !== " + locationHost));
238 return done(null, res);
242 it('should not touch already-encoded sequences in "url"', function (done) {
243 var app = createRedirectServerForDomain('google.com');
244 testRequestedRedirect(
245 app,
246 'https://google.com?q=%A710',
247 'https://google.com?q=%A710',
248 'google.com',
249 done
253 it('should consistently handle relative urls', function (done) {
254 var app = createRedirectServerForDomain(null);
255 testRequestedRedirect(
256 app,
257 '/foo/bar',
258 '/foo/bar',
259 null,
260 done
264 it('should not encode urls in such a way that they can bypass redirect allow lists', function (done) {
265 var app = createRedirectServerForDomain('google.com');
266 testRequestedRedirect(
267 app,
268 'http://google.com\\@apple.com',
269 'http://google.com\\@apple.com',
270 'google.com',
271 done
275 it('should not be case sensitive', function (done) {
276 var app = createRedirectServerForDomain('google.com');
277 testRequestedRedirect(
278 app,
279 'HTTP://google.com\\@apple.com',
280 'HTTP://google.com\\@apple.com',
281 'google.com',
282 done
286 it('should work with https', function (done) {
287 var app = createRedirectServerForDomain('google.com');
288 testRequestedRedirect(
289 app,
290 'https://google.com\\@apple.com',
291 'https://google.com\\@apple.com',
292 'google.com',
293 done
297 it('should correctly encode schemaless paths', function (done) {
298 var app = createRedirectServerForDomain('google.com');
299 testRequestedRedirect(
300 app,
301 '//google.com\\@apple.com/',
302 '//google.com\\@apple.com/',
303 'google.com',
304 done
308 it('should percent encode backslashes in the path', function (done) {
309 var app = createRedirectServerForDomain('google.com');
310 testRequestedRedirect(
311 app,
312 'https://google.com/foo\\bar\\baz',
313 'https://google.com/foo%5Cbar%5Cbaz',
314 'google.com',
315 done
319 it('should encode backslashes in the path after the first backslash that triggered path parsing', function (done) {
320 var app = createRedirectServerForDomain('google.com');
321 testRequestedRedirect(
322 app,
323 'https://google.com\\@app\\l\\e.com',
324 'https://google.com\\@app%5Cl%5Ce.com',
325 'google.com',
326 done
330 it('should escape header splitting for old node versions', function (done) {
331 var app = createRedirectServerForDomain('google.com');
332 testRequestedRedirect(
333 app,
334 'http://google.com\\@apple.com/%0d%0afoo:%20bar',
335 'http://google.com\\@apple.com/%0d%0afoo:%20bar',
336 'google.com',
337 done
341 it('should encode unicode correctly', function (done) {
342 var app = createRedirectServerForDomain(null);
343 testRequestedRedirect(
344 app,
345 '/%e2%98%83',
346 '/%e2%98%83',
347 null,
348 done
352 it('should encode unicode correctly even with a bad host', function (done) {
353 var app = createRedirectServerForDomain('google.com');
354 testRequestedRedirect(
355 app,
356 'http://google.com\\@apple.com/%e2%98%83',
357 'http://google.com\\@apple.com/%e2%98%83',
358 'google.com',
359 done
363 it('should work correctly despite using deprecated url.parse', function (done) {
364 var app = createRedirectServerForDomain('google.com');
365 testRequestedRedirect(
366 app,
367 'https://google.com\'.bb.com/1.html',
368 'https://google.com\'.bb.com/1.html',
369 'google.com',
370 done
374 it('should encode file uri path', function (done) {
375 var app = createRedirectServerForDomain('');
376 testRequestedRedirect(
377 app,
378 'file:///etc\\passwd',
379 'file:///etc%5Cpasswd',
381 done