php 理解“发布/重定向/获取”模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10827242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding the "post/redirect/get" pattern
提问by whatdafrak
I am having a very hard time understanding the exact process of "post/redirect/get".
我很难理解“发布/重定向/获取”的确切过程。
I have combed through this site and the web for several hours and cannot find anything other than "here's the concept".
我已经梳理了这个网站和网络几个小时,除了“这是概念”之外,找不到任何其他东西。
How to understand the post/redirect/get pattern?
如何理解 post/redirect/get 模式?
采纳答案by icktoofay
As you may know from your research, POST-redirect-GETlooks like this:
您可能从研究中POST了解到,-redirect-GET如下所示:
- The client gets a page with a form.
- The form
POSTs to the server. - The server performs the action, and then redirects to another page.
- The client follows the redirect.
- 客户端获取带有表单的页面。
- 表单
POSTs 到服务器。 - 服务器执行操作,然后重定向到另一个页面。
- 客户端遵循重定向。
For example, say we have this structure of the website:
例如,假设我们有这样的网站结构:
/posts(shows a list of posts and a link to "add post")/<id>(view a particular post)/create(if requested with theGETmethod, returns a form posting to itself; if it's aPOSTrequest, creates the post and redirects to the/<id>endpoint)
/posts(显示帖子列表和“添加帖子”的链接)/<id>(查看特定帖子)/create(如果使用该GET方法请求,则返回一个发布给自身的表单;如果它是一个POST请求,则创建发布并重定向到/<id>端点)
/postsitself isn't really relevant to this particular pattern, so I'll leave it out.
/posts本身与这个特定的模式并没有真正的相关性,所以我将把它排除在外。
/posts/<id>might be implemented like this:
/posts/<id>可能是这样实现的:
- Find the post with that ID in the database.
- Render a template with the content of that post.
- 在数据库中查找具有该 ID 的帖子。
- 使用该帖子的内容呈现模板。
/posts/createmight be implemented like this:
/posts/create可能是这样实现的:
- If the request is a
GETrequest:- Show an empty form with the target set to itself and the method set to
POST.
- Show an empty form with the target set to itself and the method set to
- If the request is a
POSTrequest:- Validate the fields.
- If there are invalid fields, show the form again with errors indicated.
- Otherwise, if all fields are valid:
- Add the post to the database.
- Redirect to
/posts/<id>(where<id>is returned from the call to the database)
- 如果请求是
GET请求:- 显示一个空表单,目标设置为自身,方法设置为
POST。
- 显示一个空表单,目标设置为自身,方法设置为
- 如果请求是
POST请求:- 验证字段。
- 如果存在无效字段,请再次显示表单并指出错误。
- 否则,如果所有字段都有效:
- 将帖子添加到数据库中。
- 重定向到
/posts/<id>(<id>从调用数据库返回的位置)
回答by Sarel Botha
I'll try explaining it. Maybe the different perspective does the trick for you.
我会试着解释一下。也许不同的视角对你有用。
With PRG the browser ends up making two requests. The first request is a POST request and is typically used to modify data. The server responds with a Location header in the response and no HTML in the body. This causes the browser to be redirected to a new URL. The browser then makes a GET request to the new URL which responds with HTML content which the browser renders.
使用 PRG,浏览器最终会发出两个请求。第一个请求是 POST 请求,通常用于修改数据。服务器在响应中使用 Location 标头进行响应,而正文中没有 HTML。这会导致浏览器被重定向到一个新的 URL。然后浏览器向新 URL 发出 GET 请求,该请求以浏览器呈现的 HTML 内容进行响应。
I'll try to explain why PRG should be used. The GET method is never supposed to modify data. When a user clicks a link the browser or proxy server may return a cached response and not send the request to the server; this means the data wasn't modified when you wanted it to be modified. Also, a POST request shouldn't be used to return data because if the user wants to just get a fresh copy of the data they're forced to re-execute the request which will make the server modify the data again. This is why the browser will give you that vague dialog asking you if you are sure you want to re-send the request and possibly modify data a second time or send an e-mail a second time.
我将尝试解释为什么应该使用 PRG。GET 方法永远不应该修改数据。当用户点击链接时,浏览器或代理服务器可能会返回缓存的响应,而不是将请求发送到服务器;这意味着当您想要修改数据时,数据并未被修改。此外,不应使用 POST 请求返回数据,因为如果用户只想获取数据的新副本,他们将被迫重新执行请求,这将使服务器再次修改数据。这就是为什么浏览器会给您一个模糊的对话框,询问您是否确定要重新发送请求并可能再次修改数据或再次发送电子邮件。
PRG is a combination of POST and GET that uses each for what they are intended to be used for.
PRG 是 POST 和 GET 的组合,它们分别使用它们的预期用途。
回答by imatwork
Just so people can see a code example (this is using express):
只是为了让人们可以看到一个代码示例(这是使用 express):
app.post('/data', function(req, res) {
data = req.body; //do stuff with data
res.redirect('public/db.html');
});
So to clarify, it instantly refreshes the webpage and so on refresh of that webpage (e.g. if you updated an element on it) it won't repost the form data.
所以澄清一下,它会立即刷新网页,并刷新该网页(例如,如果您更新了其中的元素),它不会重新发布表单数据。
My code used to look like this:
我的代码曾经是这样的:
app.post('/data', function(req, res) {
data = req.body;
res.sendFile('public/db.html');
});
So here the response is sending the html file at the /data address. So in the address bar, after pressing the submit button it would say for me: localhost:8080/data.
But this means that on refresh of that page, if you have just submitted the form, it will submit it again. And you don't want the same form submitted twice in your database. So redirecting it to the webpage (res.redirect) instead of sending the file (res.sendFile) , stops the resubmission of that form.
所以这里的响应是在 /data 地址发送 html 文件。所以在地址栏中,按下提交按钮后,它会为我说:localhost:8080/data. 但这意味着在刷新该页面时,如果您刚刚提交了表单,它将再次提交。并且您不希望在您的数据库中两次提交相同的表单。因此,将其重定向到网页 ( res.redirect) 而不是发送文件 ( res.sendFile) 会停止重新提交该表单。
回答by challet
It is all a matter of concept, there is no much more to understand :
这都是一个概念问题,没有更多需要理解的:
- POST is for the client to send data to the server
- GET is for the client to request data from the server
- POST 是让客户端向服务器发送数据
- GET 是让客户端向服务器请求数据
So, conceptually, there is no sense for the server to answer with a resource data on a POST request, that's why there is a redirection to the (usually) same resource that has been created/updated. So, if POST is successful, the server opiniates that the client would want to fetch the fresh data, thus informing it to make a GET on it.
因此,从概念上讲,服务器在 POST 请求上回答资源数据是没有意义的,这就是重定向到(通常)已创建/更新的相同资源的原因。因此,如果 POST 成功,服务器会认为客户端想要获取新数据,从而通知它对其进行 GET。


