对 HTTP POST 请求的正确响应是什么?

发布于 2024-07-11 12:56:31 字数 1455 浏览 6 评论 0原文

对于 POST 方法,W3 规范规定:

如果源服务器上已经创建了资源,则响应 应为 201(已创建)并包含一个描述 请求的状态并引用新资源和位置 标头(参见第 10.4 节)。

http://www.ietf.org/internet -drafts/draft-ietf-httpbis-p2-semantics-05.txt(第 8.5 节)

标准响应实际上似乎是将重定向发送到新创建的资源。

我正在使用 ASP.NET MVC 构建我的网站,并尝试遵循规范,因此创建了一个 ResourceCreatedResult 类:

public class ResourceCreatedResult : ActionResult
{
    public string Location { get; set; }
    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.StatusCode = 201;
        context.HttpContext.Response.ClearHeaders();
        context.HttpContext.Response.AddHeader("Location", Location);
    }
}

我的操作看起来像这样:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateNew(string entityStuff)
{
    Entity newEntity = new Entity(entityStuff);
    IEntityRepository entityRepository = ObjectFactory.GetInstance<IEntityRepository>();
    entityRepository.Add(newEntity);

    ActionResult result = new ResourceCreatedResult()
        { Location = Url.Action("Show", new { id = newEntity.Id }) };
    return result;
}

但是,IE、Firefox 和 Chrome 都无法重定向到新资源。 我是否搞砸了生成正确的响应,或者 Web 浏览器不期望这种类型的响应,而是依赖服务器发送重定向响应?

For a POST method, the W3 specs say:

If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see Section 10.4).

http://www.ietf.org/internet-drafts/draft-ietf-httpbis-p2-semantics-05.txt (section 8.5)

The standard response actually seems to be to send a Redirect to the newly created resource.

I'm building my site with ASP.NET MVC, and tried to follow the spec, so created a ResourceCreatedResult class:

public class ResourceCreatedResult : ActionResult
{
    public string Location { get; set; }
    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.StatusCode = 201;
        context.HttpContext.Response.ClearHeaders();
        context.HttpContext.Response.AddHeader("Location", Location);
    }
}

And my action looks something like this:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateNew(string entityStuff)
{
    Entity newEntity = new Entity(entityStuff);
    IEntityRepository entityRepository = ObjectFactory.GetInstance<IEntityRepository>();
    entityRepository.Add(newEntity);

    ActionResult result = new ResourceCreatedResult()
        { Location = Url.Action("Show", new { id = newEntity.Id }) };
    return result;
}

However, IE, Firefox and Chrome all fail to redirect to the new resource. Have I messed up generating the correct response, or do web browsers not expect this type of response, instead relying on servers to send a Redirect response?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

醉城メ夜风 2024-07-18 12:56:31

为了用户友好,您的应用程序必须在发布后或发布/重定向/获取后重定向。

编辑。 这超出了 HTTP 规范。 如果我们在 POST 后简单地返回 201,浏览器后退按钮的行为就会很糟糕。

请注意,Web 服务请求(不响应浏览器)完全遵循标准,并且在发布后不会重定向。

它的工作原理是这样的。

  1. 浏览器发布数据。

  2. 您的应用程序验证数据。 如果无效,您可以使用表单进行响应,以便他们可以修复它并发布。

  3. 您的应用程序以重定向进行响应。

  4. 浏览器获取重定向并执行 GET。

  5. 您的应用程序看到 GET 并响应。

现在——嘿,快点! -- 后退按钮有效。

Redirect after post or post/redirect/get is something your application must do to be user friendly.

Edit. This is above and beyond the HTTP specifications. If we simply return a 201 after a POST, the browser back button behaves badly.

Note that Web Services requests (which do NOT respond to a browser) follow the standard completely and do NOT redirect after post.

It works like this.

  1. The browser POSTS the data.

  2. Your application validates the data. If it's invalid, you respond with the form so they can fix it and POST.

  3. Your application responds with a redirect.

  4. The browser gets the redirect and does a GET.

  5. Your application sees the GET and responds.

Now -- hey presto! -- the back button works.

黑白记忆 2024-07-18 12:56:31

明确地说,浏览器(包括 Firefox 3 和 IE8 等现代浏览器)不会“接受提示”,而是通过对 Location 标头中提供的 URI 发出 GET 请求来跟踪 HTTP 201: Created 响应。

如果您希望浏览器转到 Location 标头中提供的 URI,则应发送 HTTP 303:查看其他 状态。

To be explicit, browsers (including modern browsers like Firefox 3 and IE8) do not "take the hint" and follow up an HTTP 201: Created response with a GET request to the URI supplied in the Location header.

If you want browsers to go to the URI supplied in the Location header, you should send an HTTP 303: See Other status instead.

过期情话 2024-07-18 12:56:31

正如规范中所述,响应应该是带有重定向的 HTTP 201。 因此,浏览器供应商并不强制要求实现正确的答案...

您应该尝试更改为 30x 代码以查看其是否正确重定向。 如果是这样,这是一个浏览器问题,否则它可能来自您的代码(我对 ASP.NET 不了解,所以我无法“验证”您的代码)

As stated in the spec the response SHOULD be a HTTP 201 with redirect. So it isn't mandatory for a browser vendor to implement the correct answer...

You should try to change to a 30x code to see if it is correctly redirected. If so, it's a browser problem, else it may come from your code (I don't know anything in ASP.NET so I can't "validate" your code)

策马西风 2024-07-18 12:56:31

难道这不应该只在“创建”某些内容时才算数,因此简单的重定向到操作应该真正足够了吗?

Shouldn't that only count for when something is "Created" and therefore a simple redirect to action should be genuinely sufficient?

み零 2024-07-18 12:56:31

我的解决方案是使用“201 Created”进行响应,其中包含一个带有新资源链接的简单页面,以及使用 location.replace() 的 JavaScript 重定向。

这使得相同的代码可以处理 API 和浏览器请求,可以很好地使用“后退”和“刷新”按钮,并且可以在旧浏览器中优雅地降级。

My solution is to respond with a '201 Created' containing a simple page with a link to the new resource, and a javascript redirect using location.replace().

This lets the same code work for API and browser requests, plays nicely with Back and Refresh buttons, and degrades gracefully in old browsers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文