一文领略状态码302与303的区别

1,232 阅读5分钟

上篇文章,我们解析了301与302之间的区别,这篇文章,还是一如既往,通过实践的方式让大家去领会状态码302与303之间的区别。

需要注意,302状态码我们不会再去讲解,如果想了解301与302,请看这篇文章

搭建环境

前端项目

执行以下命令:

// 1、创建项目
npx create-react-app font

// 2、进入到项目根目录
cd font

// 3、安装依赖
npm install

// 4、暴露配置
npm run eject

// 5、运行项目
npm run start

后端项目

执行以下命令:

// 1、第一步(安装express脚手架) 
npm install -g express-generator 

// 2、第二步(使用脚手架创建一个名为“end”的项目) 
express end 

// 3、第三步(进入项目目录) 
cd end 

// 4、第四步(安装项目依赖) 
npm install 

// 5、修改后端项目的端口号

// 6、第五步(启动项目) 
npm run start

修改端口号的操作如下:

截屏2023-10-25 22.38.21.png

接着,我们来为本次的内容注册专门的路由:

修改routes目录下的users文件,修改后文件内容如下:

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

router.post('/303OldUrl', function(req, res, next) {
  res.redirect(303, '/users/303NewUrl')
});

router.post('/303NewUrl', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

实现跨域资源共享

这个知识点在这里不做过多描述,进入到后端项目的目录下,安装cors模块,执行以下命令:

npm install cors

依赖安装成功后,修改项目根目录下的app.js文件如下:

截屏2023-10-26 19.35.56.png

好的,接下来,我们需要修改前端项目来测试这个ajax这个流程是否可以跑通。

新增Page页面,并且为这个页面单独开启一个路由,Page页面内容如下:

import React, { useState } from 'react';
import axios from 'axios';
import { Input, message } from 'antd';

function Page(props){
    let [inputValue, setInputValue] = useState('');

    const send303Req = () => {
        let result = await axios.create({
            baseURL: 'http://127.0.0.1:8888/'
        })
        .get('/users', {
            firstName: 'Fred',
            lastName: 'Flintstone'
        })
        .then(function (response) {
            console.log('收到的响应:', response);
            return response
        })
        .catch(function (error) {
            console.log('响应出错了:', error);
            return error;
        });
        if (result.status == 200){
            message.success('收到了成功的响应!');
        }
    }

    return <div className='page'>
        <Input placeholder="请输入内容" value={inputValue}/>;
        <button onClick={send303Req}>303</button>
    </div>
}

export default Page;

分别启动前后端项目,项目全都启动成功后,我们在浏览器里输入:http://127.0.0.1:3000/page

截屏2023-10-26 20.11.08.png

点击按钮发送请求,根据我们代码来看,如果返回成功200,并且页面上有一个提示框,那么前后端的流程就算成功的打通了。

截屏2023-10-26 20.14.50.png

303状态码

303 See Other(查看其他位置)。表示请求已经完成,但服务器应该告诉浏览器应该使用一个新的URL来访问资源,与302不同的是,此状态码要求后续请求使用GET方法来获取资源。

流程讲解

  • 我们发送一个post请求,并且携带了请求体。
  • 后端处理请求,返回303状态码,并且返回一个最新的资源地址。
  • 浏览器使用GET方法去请求最新的资源地址, 并且,浏览器会忽略掉第一次请求携带的请求体
  • 如果最新的资源地址是GET方法,那么浏览器将会收到成功的响应。
  • 如果最新的资源地址是POST方法,那么浏览器将会收到404的响应。

动手实践

我们先来修改一下前端发送请求的地址为/users/303OldUrl,请求方式修改为post。

const send303Req = async () => {
    let result = await axios.create({
        baseURL: 'http://127.0.0.1:8888/'
    })
    .post('/users/303OldUrl', {
        firstName: 'Fred',
        lastName: 'Flintstone'
    })
    .then(function (response) {
        console.log('收到的响应:', response);
        return response
    })
    .catch(function (error) {
        console.log('响应出错了:', error);
        return error;
    });
    if (result.status == 200){
        message.success('收到了成功的响应!');
    }
    if (result.status != 200){
        message.error('请求地址404 ...');
    }
}

截屏2023-10-26 20.16.40.png

根据后端的路由来看,这次请求的结果最终一定是个404,因为最新的资源地址是post方法,但是浏览器访问最新的资源地址是一个get请求。

截屏2023-10-26 20.40.32.png

此时我们如果来修改一下后端的最新资源的请求方法为GET,

截屏2023-10-26 20.45.04.png

当我们再次发送请求的时候,我们会发现此时是一个正常的响应,但是请求body依然会被干掉。

截屏2023-10-26 20.49.09.png

最后

其实如果你以同样的方式去测试302状态码的话,你会发现,302跟303状态码好像没区别,第二次请求都会被处理成get请求,请求体都会被废弃。那它俩有啥区别?

根据HTTP规范,302状态码在实际应用中经常被浏览器错误地处理为GET请求。

实际上,根据RFC 7231,当接收到302状态码时,客户端(浏览器)在遵循重定向时可以使用GET方法或者保持原始请求方法。但是,大多数浏览器会自动将POST请求转换为GET请求,这是由于历史上的一些安全和兼容性问题。

为了确保一致性和可预测性,HTTP/1.1引入了303状态码。当服务器返回303状态码时,客户端应该使用GET方法获取重定向的资源。所以根据标准,如果您希望在POST请求后进行重定向并期望客户端使用GET方法获取新的资源,应该返回303状态码。

最后的最后

好啦,本篇文章到这里就结束啦,如果本篇文章对你有帮助,欢迎一键四连。如果上述过程中有错误,也还请各路大神指正,那么,我们下期再见啦,👋👋👋。