Express是一个基于Node.js实现的Web框架,其响应HTTP请求的response
对象中有两个用于URL跳转方法res.location()
和res.redirect()
,使用它们可以实现URL的301或302重定向。
res.location()
res.redirect()
- 方法分析与对比
- 3.1 URL重定向原理
- 3.2
location()
与redirect()
的比较 - 3.3 重定向与不重定向
1. res.location()
res.location(path)
设置响应的HTTP Location
头。path
可以是以下几种设置形式:
res.location('/foo/bar'); res.location('../login'); res.location('http://itbilu.com'); res.location('back');
path
参数可以是一个绝对路径、相对路径、标准URL或是'back'
。当path
是'back'
时,响应的Location
头会被设置为当前请求的Referer
头,当Referer
头不存在时会被设置为'/'
。
Express
通过Location
头将指定的URL字符串传递给浏览器,它并不会对指定的字符串进行验证(除'back'
外)。而浏览器则负责将当前URL重定义到响应头Location
中指定的URL。
2. res.redirect()
res.redirect([status,] path)
参数
status
:{Number},表示要设置的HTTP状态码path
:{String},要设置到Location
头中的URL
重定义到path
所指定的URL,重定向时可以同时指定HTTP状态码,不指定状态码默认为302
与location()
相比,redirect()
除了要设置path
外,还可以指定一个状态码。而path
参数则与location()
完全相同。
使用redirect()
重定向时,可以是几下几种设置方式:
res.redirect('/foo/bar'); res.redirect('http://itbilu.com'); res.redirect(301, 'http://itbilu.com'); res.redirect('http://itbilu.com', 301); res.redirect('../login'); // /blog/post/1 -> /blog/login res.redirect('back');
3. 分析与对比
3.1 URL重定向原理
进行URL重定向时,服务器只在响应信息的HTTP头信息中设置了HTTP状态码
和Location
头信息。
当状态码为301
或302
时(301
-永久重定向、302
-临时重定向),表示资源位置发生了改变,需要进行重定向。
Location
头信息表示了资源的改变的位置,即:要跳重定向的URL。
3.2 location()
与redirect()
的比较
Express
的response
对象,是对Node.js原生对象ServerResponse
的扩展。location()
方法只会设置Location
头,而redirect()
方法除了会设置Location
头外还可自动或手头设置HTTP状态码
。理论上讲两者可以实现重定向。
location()
方法
location()
方法实现过程大致如下:
res.location = function(url){ var req = this.req; // "back" 是 referrer的别名 if ('back' == url) url = req.get('Referrer') || '/'; // 设置Lcation this.setHeader('Location', url); return this; };
从以上代码可以看出,location()
方法本质上是调用了ServerResponse
对象的setHeader()
方法,但并没有设置状态码。通过location()
设置头信息后,其后的代码还会执行。
使用location()
方法实现URL的重定向,还要手动设置HTTP状态码
:
res.location('http://itbilu.com'); res.statusCode = 301;
如果需要立即返回响应信息,还要调用end()
方法:
res.location('http://itbilu.com'); res.statusCode = 301; res.end('响应的内容'); // 或 res.location('http://itbilu.com'); res.sent(302);
redirect()
方法
redirect()
方法实现过程大致如下:
res.redirect = function(url){ var head = 'HEAD' == this.req.method; var status = 302; var body; // 一些处理 …… // 通过 location 方法设置头信息 this.location(url); // 另一些处理 …… // 设置状态并返回响应 this.statusCode = status; this.set('Content-Length', Buffer.byteLength(body)); this.end(head ? null : body); };
从以上代码可以看出,redirect()
方法是对location()
方法的扩展。通过location()
设置Loction
头后,设置HTTP状态码
,最后通过ServerResponse
对象的end()
方法返回响应信息。调用redirect()
方法后,其后的代码都不会被执行。
3.3 重定向与不重定向
在使用的过程中,redirect()
方法大多能重定向成功,而location()
方法则不太确定,有时可以成功有时不能成功。这与我们的用法有关。
上面讲过,URL重定向是在浏览器端完成的,而URL重定向与HTTP状态码
和Location
头有关。浏览器首先会判断状态码,只有当状态码是:301
或302
时,才会根据Location
头中的URL进行跳转。
所以,使用location()
设置头信息,而不设置状态码或状态码不是301
或302
,并不会发生重定向:
res.location('http://itbilu.com'); res.sent(200);
而使用redirect()
设置的状态码不是301
或302
也不会发生跳转:
res.redirect(200, 'http://itbilu.com');