res.location()与res.redirect()

Express URL跳转(重定向)的实现:res.location()与res.redirect()

 2016年03月02日     1521     声明


Express是一个基于Node.js实现的Web框架,其响应HTTP请求的response对象中有两个用于URL跳转方法res.location()res.redirect(),使用它们可以实现URL的301或302重定向。


  1. res.location()
  2. res.redirect()
  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重定向原理

进行URL重定向时,服务器只在响应信息的HTTP头信息中设置了HTTP状态码Location头信息。

当状态码为301302时(301-永久重定向、302-临时重定向),表示资源位置发生了改变,需要进行重定向。

Location头信息表示了资源的改变的位置,即:要跳重定向的URL。


3.2 location()redirect()的比较

Expressresponse对象,是对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头有关。浏览器首先会判断状态码,只有当状态码是:301302时,才会根据Location头中的URL进行跳转。

所以,使用location()设置头信息,而不设置状态码或状态码不是301302,并不会发生重定向:

res.location('http://itbilu.com');
res.sent(200);

而使用redirect()设置的状态码不是301302也不会发生跳转:

res.redirect(200, 'http://itbilu.com');
router.beforeEach((to, from, next) => { if (store.getters.getRouters == null) { // 获取菜单和路由 getMenusApi(params).then((res) => { if (res.data.length === 0) { window.location.href = process.env.VUE_APP_API_BASE_CONSOLE || '' } const { data } = res const menuNav = [] const childrenNav = [] // 后端数据, 根级树数组, 根级 PID listToTree(data, childrenNav, 0) menuNav.push(...childrenNav) const routers = generator(menuNav, null) routers.forEach((r) => { router.addRoute(r) }) router.addRoute(page404) store.commit('SET_ROUTERS', routers[0].children) // 请求带有 redirect 重定向时,登录自动重定向到该地址 const redirect = decodeURIComponent(from.query.redirect || to.path) if (to.path === redirect) { // set the replace: true so the navigation will not leave a history record next({ ...to, replace: true }) } else { // 跳转到目的路由 next({ path: redirect }) } }).catch((error) => { console.log(error,'error') if (error.data.code !== 200 || error.data.data.length === 0) { setTimeout(function () { window.location.href = process.env.VUE_APP_API_BASE_CONSOLE || '' }, 5) } }) // // 获取按钮权限 // getPermissionApi(params).then((res: any) => { // if (res.data.code !== 200) return ElMessage.error(res.data.message) // store.commit('SET_PERMISSION', res.data.data) // }) // // 获取数据权限 // getRolesApi(params).then((res: any) => { // if (res.data.code !== 200) return ElMessage.error(res.data.message) // store.commit('SET_ROLES', res.data.data) // }) // // 获取用户信息 // getUserInfoApi().then((res: any) => { // if (res.data.code !== 200) return ElMessage.error(res.data.message) // store.commit('SET_USERS', res.data.data) // }) } else { next() } })
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值