本文首发于:https://github.com/bigo-frontend/blog/ 欢迎关注、转载。

前言

前段时间接手了一个项目,在代码中看到了这样的一段代码:

    if (isHTML(data) &&response.request.responseURL?.indexOf(CAS_PREFIX) > -1) {window.location.href = response.request.responseURL;}

主要的作用就是当后端响应的内容是html的时候,跳转到登录页面。这种方案让我感觉有点别扭,于是具体了解了这段代码出现的原因。

功能的核心在于用户鉴权,后端设想的方案是:当前端发起接口请求,后端识别到用户未登录的时候,就会给前端响应302的状态码,以为很方面,前端不用处理就直接跳转到了登录页面。

然而,他们不知道的是,前端发起的ajax请求,并不能直接跳转,甚至连302状态码都捕获不到。

常见状态码

HTTP 响应状态代码指示特定 HTTP 请求是否已成功完成。响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599)。

  • 200: 请求成功
  • 301:永久重定向
  • 302:临时重定向
  • 303:硬糖少女
  • 304:内容未改变
  • 4:阿森纳
  • 401:需要验证
  • 403:拒绝访问
  • 404:找不到
  • 500:服务器异常

更多状态码:传送门

我们知道,浏览器对于不同的状态码,会有不同的行为。那当返回302的时候,浏览器会有什么样的反应呢?

浏览器处理302状态码

重定向,顾名思义,就是把请求重新指向了一个新的地址。

当浏览器发起一个请求,服务端返回了302状态码,这时候浏览器会根据响应头中的location字段,重新发起一个请求。当重定向次数过多的时候,浏览器会抛出ERR_TOO_MANY_REDIRECT的异常。

请求分两种情况:

  • 浏览器页面请求:跳转到新的页面。
  • ajax请求:返回最后重定向地址的响应。这种重定向,会有可能出现跨域的问题。

前面提到的,服务端觉得返回302很方便,大概是以为ajax也会跳转到新页面吧。

阻止ajax重定向

使用fetch Api进行请求的时候,可以通过redirect参数配置如何处理重定向。

redirect可选的值有三个:

  • follow:自动重定向
  • error:如果产生重定向将自动终止并且抛出一个错误TypeError: Failed to fetch
  • manual:手动处理重定向

在Chrome中默认使用follow(Chrome 47之前的默认值是manual)。

当我们设置成manual时,如果发生了重定向,会拿到type为opaqueredirect的response:

{"body": null,"bodyUsed": false,"headers": {},"ok": false,"redirected": false,"status": 0,"statusText": "","type": "opaqueredirect","url": "https://xxx.com",
}

一般来说,我们是不需要手动处理重定向的,因为你不知道这个重定向是否是就是因为未登录才产生的重定向。

如何处理未登录跳转的问题

当用户未登录时,我们除了302状态码之外,可以选择使用401或403状态码,这样至少前端可以捕获到,并作出跳转的处理。

在项目中,我们和服务端的协议格式基本都是json,响应的内容格式如下:

{"code": 0,"data": null,"msg": "ok"
}

一般来说,服务端都会响应200的http状态码,然后使用body里面的code字段标识业务异常。所以当用户未登录时,响应以下内容,也是不错的选择:

{"code": 40401,"data": "https://login.xxx.com","msg": "Unauthorized"
}

如果的确要考虑自动跳转的场景,可以在服务端区分一下请求是来源于页面请求还是ajax请求,然后根据不同的请求响应不一样的内容即可。比如以Express为例:

// The user needs to login again
if (req.xhr) {res.status(200).json({code: 40401,data: 'https://login.xxx.com',msg: "Unauthorized"})
} else {res.redirect('https://login.xxx.com')
}

另外,我们还可以利用Accept请求头来区别响应。

Accept 请求头用来告知(服务器)客户端可以处理的内容类型,这种内容类型用MIME类型来表示。借助内容协商机制, 服务器可以从诸多备选项中选择一项进行应用,并使用 Content-Type 应答头通知客户端它的选择。浏览器会基于请求的上下文来为这个请求头设置合适的值,比如获取一个CSS层叠样式表时值与获取图片、视频或脚本文件时的值是不同的。

常见的,直接在浏览器导航栏打开一个地址,Accept的值大概会是Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9;ajax请求,会是:Accept: application/json, text/javascript, */*; q=0.01。其中;q= (q因子权重)的值代表权重。

更多Accept介绍:传送门

后语

最后,点一下题。当后端给你返回了302,在他们看来,应该是这样的:

然而,在前端看来,却是这样的:

以上,简单探讨了常见又不常处理的状态码302,如有错漏,欢迎指正!

欢迎大家留言讨论,祝工作顺利、生活愉快!

我是bigo前端,下期见。

当后端给我返回了302状态码相关推荐

  1. 302状态码_http状态码是什么?301 302 404的SEO应用场景

    什么是HTTP状态码?简单的讲,就是用以表示网页服务器HTTP响应状态的3位数字代码.其中1xx表示临时响应,2xx表示成功处理了请求,3xx代表重定向,4xx表示请求错误,而5xx表示服务器错误.除 ...

  2. 302状态码_HTTP协议详解(基础概念 方法 状态码 首部 连接 Cookie 新特性 安全)

    一 .基础概念 URI URI 包含 URL 和 URN. 请求和响应报文 1. 请求报文 2. 响应报文 二.HTTP 方法 客户端发送的 请求报文 第一行为请求行,包含了方法字段. GET 获取资 ...

  3. 谈谈301状态码和302状态码的区别

    本篇文章主要从多个角度对301和302状态码进行不同方面的解读. 作者:任聪聪 日期:2021-7-9 一.301和302的区别和意义 程序方向来讲这两个状态码,实际上没有多大的区别,都是跳转的返回状 ...

  4. 浏览器返回的常见状态码

    HTTP http: 超文本传输协议,在传输层采用的是TCP协议.浏览器与服务器建立连接时会经过TCP的三次握手,一次TCP的连接可以建立多个HTTP请求.状态码为服务器接受请求之后返回的响应信息,浏 ...

  5. 302PHP状态码,HTTP 302 状态码

    HTTP 302 状态码 302 Found 要求客户端执行临时重定向(原始描述短语为"Moved Temporarily").由于这样的重定向是临时的,客户端应当继续向原有地址发 ...

  6. 304,301,302状态码的分析

    1.304 服务器可以设置缓存机制,这个功能是为了提高网站的访问速度,当你发出一个GET请求的时候服务器会从缓存中调用你要访问的内容,这个时候服务器就可以判断这个页面是不是更新过了,如果未更新过那么他 ...

  7. 301和302状态码区别

    一.官方解释 301 redirect: 301 代表永久性转移(Permanently Moved) 302 redirect: 302 代表暂时性转移(Temporarily Moved ) 30 ...

  8. 302状态码_你见过 HTTP 哪些状态码?

    ❝ 好久没有写技术文章,今天在四川广元无事,总结一篇.附一张今天早上在嘉陵江遇见的白鹡鸰 (不是我拍的) ❞ 白鹡鸰 101 Switch Protocol 200 Ok 201 Created 20 ...

  9. 302状态码_HTTP状态码status code详解

    http状态码可以让我很方便的了解到请求的所在状态,所以很有必要总结一下,对今后的学习也是很有帮助的. 什么是HTTP状态码 HTTP状态码的作用是:web服务器用来告诉客户端,发生了什么事. 状态码 ...

最新文章

  1. pythonisodd函数_python3.5|小白入门基础语法之数据结构、函数、迭代,确实简洁...
  2. 一个判断射线和三角形相交的函数
  3. Qt第三方库QCustomPlot——认识图表的各个部分
  4. 台湾大学林轩田机器学习技法课程学习笔记10 -- Random Forest
  5. python 测试用例怎么输入两个_python selenium多个测试用例
  6. Longest Common Substring
  7. 看全域消费者运营Quick Audience如何实现自动化营销?
  8. SpringCloud(第 054 篇)简单 Quartz-Cluster 微服务,采用注解配置 Quartz 分布式集群...
  9. 如何在Django模板中注入全局变量
  10. 持续集成之Jenkins安装部署
  11. LeetCode 632. 最小区间(排序+滑动窗口)
  12. 译文 | 与TensorFlow的第一次接触 第三章:聚类
  13. python爬虫爬取页面源码在本页面展示
  14. 浏览器跨域问题(jsonp)——jsonp详解
  15. 北京大学计算机学院周磊,马秀莉-北京大学信息科学技术学院
  16. java生成和识别二维码
  17. 网络安全技术心得体会
  18. 四省卫视联手办春晚 展现各地风俗年味
  19. cisco2811语音网关+callmanager拨打外线,外线拨入详解配置
  20. spring报错→UnexpectedRollbackException: Transaction silently rolled back becaus

热门文章

  1. 基于单片机智能加湿器 水位防干烧加湿器的设计与实现
  2. linux编译linphone,Ubuntu下linphone交叉编译与移植
  3. 进程调度算法-先来先服务调度算法(FCFS)
  4. udt编写高性能服务器,基于UDT协议的文件传输服务的设计与实现
  5. 二分法求最值:面向答案编程
  6. Echarts矩形树图
  7. 装完docker电脑黑屏无法启动_Docker入门踩坑实录
  8. 肺结节CT影像特征提取(一)——肺结节CT图像特征概要
  9. 淘宝卖家订单商品接口解决方案
  10. 高可用 - 06 Keepalived基础功能应用实例