Post/Redirect/Get (PRG) 是一种网络开发设计模式,目的在于避免重复的表单提交,为用户建立更加直观的体验。PRG支持如书签和刷新按钮等可预测行为的场景,避免表单的重复提交。
表单通过HTTP POST提交后,用户在浏览器中刷新提交的地址,会导致原来的HTTP POST请求内容重复提交,可能会导致不希望的结果,如订单的重复提交。
为了避免该问题,开发者使用PRG模式——代替了直接返回一个页面,而是返回重定向命令。HTTP 1.1 标准推荐在该情况下使用HTTP 303(对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI) 状态码,用户可以在浏览器中安全的进行刷新而不会导致表单的重复提交。然而,当前大多数的商业应用仍然使用有问题的HTTP 302(Found)状态码来处理。
PRG模式没法涵盖所有的表单重复提交的场景。一些已知的场景为:
- 在服务端延迟的情况下,请求还没有完成处理,用户在浏览器端进行了刷新,将会导致重复的表单提交。
为了避免表单的重复提交,服务端可以使用唯一标识来标识请求。
浏览器可以用书签保存HTTP请求的URI地址。HTTP POST请求包含了带有内容的请求体,不能被当作书签保存。使用了PRG模式,HTTP GET请求的URI可以被安全的保存。 缺乏了对持久性数据的保存是书签设计的一个问题,但是书签已经可以用来代表程序运行的每一步。
由于重定向使用了绝对地址的URI,需要注意代理服务器(HTTP --> HTTPS)以及反向代理服务器。如果应用程序使用了SSL通道来访问服务,也会造成此类问题。 (可以通过 Referer headers来获取域名,端口等服务信息)