不能显式拦截ajax请求的302响应?

记录工作中早该加深印象的一个小小小case:ajax请求不能显式拦截 302响应。

我们先来看一个常规的登录case:

  1. 1. 浏览器请求资源,服务器发现该请求未携带相关凭据(cookie或者token)

  2. 2. 服务器响应302,并在响应头Location写入重定向地址, 指示浏览器跳转到登录页

  3. 3. 浏览器跳转到登录页,提交身份信息,回调到原业务站点,服务端利用Set-Cookie响应头种下cookie或者token

利用axios库发起请求[1]

Axios is a promise-based HTTP Client for node.js and the browser. It is isomorphic (= it can run in the browser and nodejs with the same codebase). On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests.

When you make an HTTP request with axios, the library returns a promise. If the request is successful (i.e. the server responds with a 2xx status code), the promise will be resolved and the then() callback will be called with the response data. On the other hand, if the request fails (i.e. the server responds with a 4xx or 5xx status code), the promise will be rejected and the catch() callback will be called with the error.

  1. 1. axios在浏览器发起的是ajax请求

  2. 2. axios默认认为2xx状态码是成功的响应, 会进入promise的resolved回调函数, 本case第一次会收到302重定向响应, 故添加ValidateStatus配置[2]

伪代码如下:

axios.request({
       method:'get',
       url:'/login',
       validateStatus: function (status) {
                return status >= 200 && status < 300 || status === 302; 
       },
   }).then((resp)=> {
     if resp.status ===302 {
         window.location.href = resp.headers['Location']
      }else{
        var userInfo = JSON.parse(
                    decodeURIComponent(
                        resp.data.msg || ""
                    ) || "{}"
                )
        this.setState({
              userInfo
        })
     }
   })

实际上以上ajax请求收到的302响应并不能被显式拦截,上面的resp实际是redirect之后的页面的响应体。

核心在于:所有浏览器都遵循了ajax标准[3]readystatus=2, All redirects (if any) have been followed and all headers of a response have been received.

翻译下来就是 :收到的响应如果有重定向,必然是重定向逻辑走完之后的响应。


对于这个常规的case, github[4]上给出的思路是:针对不同类型的http请求,服务端给出不同的状态码。

if  req.isXhr {
     c.JSON(http.StatusForbidden, gin.H{
          "code": 403,
          "msg":  redirectUrl}) 
  }else {
      c.Redirect(http.StatusFound, redirectUrl)
  }

如果是ajax请求,返回4xx json响应,让浏览器主动重定向。

axios.defaults.headers.common['X-Requested-With']="XMLHttpRequest";
 axios.request({    
            method: 'get',
            url: '/login',
            validateStatus: function (status) {
                return status >= 200 && status < 300 || status === 403; 
            },
        }).then((resp)=> {
            if (resp.status===200  && resp.data.code === 200) {
               ......
            }else{
                window.location.href = resp.data.msg
            }
        })
引用链接

[1] 利用axios库发起请求: https://www.geeksforgeeks.org/which-http-response-status-codes-result-in-then-and-which-in-catch/
[2] ValidateStatus配置: https://axios-http.com/docs/handling_errors
[3] ajax标准: https://xhr.spec.whatwg.org/#states
[4] github: https://github.com/axios/axios/issues/932#issuecomment-307390761

646a60f8717b7dcc3311bb004d5c7a3b.png全文原创,希望得到各位反馈,欢迎斧正交流, 若有更多进展,会实时更新到[左下角阅读原文]。

朝花夕拾,何足挂齿。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
拦截 AJAX 请求,你可以使用 XMLHttpRequest 对象的 onreadystatechange 事件,在该事件的回调函数中处理请求响应数据。 以下是一个示例代码: ```javascript // 创建一个新的XMLHttpRequest对象 var xhr = new XMLHttpRequest(); // 重写XMLHttpRequest的open方法 var open = xhr.open; xhr.open = function(method, url, async) { // 在发送请求之前拦截请求,可以在这里修改URL或请求头等信息 console.log('intercept request:', method, url, async); // 调用原生的open方法 open.call(xhr, method, url, async); }; // 重写XMLHttpRequest的send方法 var send = xhr.send; xhr.send = function(data) { // 在发送请求之前拦截请求体,可以在这里修改请求体的数据格式等信息 console.log('intercept request body:', data); // 调用原生的send方法 send.call(xhr, data); }; // 监听XMLHttpRequest对象的onreadystatechange事件 xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { // 在接收到响应拦截响应数据,可以在这里修改响应数据的格式等信息 console.log('intercept response:', this.responseText); } }; // 发送一个GET请求 xhr.open('GET', '/api/getData', true); xhr.send(); ``` 在上述示例代码中,我们通过重写 XMLHttpRequest 对象的 open 和 send 方法,拦截AJAX 请求,并在请求响应的各个阶段打印了一些信息。你可以在这些拦截器中添加自己的逻辑,以实现更复杂的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有态度的马甲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值