首页/网络/协议速查/PRG 模式(POST/Redirect/GET)
HTTP 方法与状态码91 条

PRG 模式(POST/Redirect/GET)

表单提交后重定向到结果页的经典模式:防止用户刷新时浏览器重复提交 POST。

协议速查网络更新于 2026-10-13

PRG 是什么

表单提交后用重定向跳到结果页的经典模式:提交请求处理成功后返回 303,浏览器再对结果页发起一次读取请求(RFC 9110 §15.4.4)。用户此后刷新页面只会重复读取,而不会重复提交表单。

为什么用 303

303 的语义就是「去看看另一个地址」,它明确要求客户端把方法改成读取。用 302 在历史上依赖浏览器的宽容行为,部分客户端可能保留原方法,刷新后又提交一次。语义最清晰的做法只有 303。

基本信息

由来终止浏览器「重新提交表单」弹窗的根本方案
实现提交成功后返回 303,并指向结果页
规范RFC 9110 §15.4.4
替代方案302 与 307 也能用,但语义不如 303 清晰

典型使用场景

  • 后台管理系统的表单提交
  • 下单、发布、审核等会产生副作用的操作
  • 服务端渲染页面的常规流程
  • 排查「刷新后重复下单」类缺陷

前后端拆分下的流程

前后端拆分下的流程
POST /submit → 303 Location: /result?id=42
GET  /result?id=42 → 200 展示结果
(用户刷新 /result 只是读取,不会重复提交)

状态码怎么选

状态码方法是否保持适用场景
303改为读取表单提交后跳转,语义最清晰
302历史实现各行其是兼容老客户端时使用,语义含糊
307保持原方法需要再次提交同一请求时
301 与 308永久重定向地址永久变更,与表单流程无关
接口型服务通常不用这个模式(客户端自己处理跳转),它主要面向浏览器表单与服务端渲染页面。
重定向后的结果页如果又做了非幂等副作用(例如再发一次通知),等于把重复问题换了个地方:刷新依旧会重复触发。
失败路径不适合重定向:把错误信息塞进查询串或用会话传递,都容易在并发与多标签场景下串号,直接渲染错误页更简单。

易错点

  • 跳转目标用 302 且方法被浏览器改成读取:语义不符,在客户端差异下容易翻车
  • 结果页做了非幂等副作用:刷新一次就再触发一次
  • 失败路径也用重定向:错误信息丢失,用户不知道发生了什么
  • 重定向目标漏了身份校验:越权读取结果页
  • 结果页依赖一次性的会话数据却没有清理:第二次刷新显示空白或报错

数据来源与参考

  • RFC 9110 §15.4.4 303 See Other

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌