使用 POST 创建请求,其响应代码为200或201以及内容

假设我编写了一个 REST 服务,其目的是向系统添加一个新的数据项。

我计划张贴到

http://myhost/serviceX/someResources

假设这样可行,那么我应该使用什么响应代码? 以及可能返回什么内容。

我正在查看 HTTP 响应代码的 定义,看到了以下可能性:

200: 返回 描述或包含行动结果的实体;

201: 这意味着创建。这意味着 * 请求已经完成,并且创建了一个新的资源。新创建的资源可以由响应实体中返回的 URI 引用,其中 Location 头字段为资源提供了最具体的 URI。响应应该包含一个包含资源特征和位置列表的实体,用户或用户代理可以从中选择最合适的一个。实体格式由 Content-Type 头字段中给定的媒体类型指定。*

后者听起来更符合 Http 规范,但我一点也不清楚是什么

响应应该包括一个实体 包含资源列表的 特征及位置

手段。

建议? 解释?

228704 次浏览

Http://www.w3.org/protocols/rfc2616/rfc2616-sec14.html#sec14.19

这只是一个冒号分隔的键值。

ETag: “ xyzzy”

它可以是任何类型的文本数据-我通常包含一个 JSON 字符串和所创建项的标识符。测试本身的易用性使得包含它是值得的。

ETag: "{ id: 1234, uri: 'http://domain.com/comments/1234', type: 'comment' }"

在本例中,标识符、 uri 和创建项的类型是“资源特征和位置”。

我认为 Atompub REST API是一个很好的静态服务的例子:

POST /edit/ HTTP/1.1
Host: example.org
User-Agent: Thingio/1.0
Authorization: Basic ZGFmZnk6c2VjZXJldA==
Content-Type: application/atom+xml;type=entry
Content-Length: nnn
Slug: First Post


<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<title>Atom-Powered Robots Run Amok</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<author><name>John Doe</name></author>
<content>Some text.</content>
</entry>

服务器的状态码为201,表示创建成功。响应包括一个 Location 头,指示 Atom Entry 的成员条目 URI,以及该条目在响应主体中的表示形式。

HTTP/1.1 201 Created
Date: Fri, 7 Oct 2005 17:17:11 GMT
Content-Length: nnn
Content-Type: application/atom+xml;type=entry;charset="utf-8"
Location: http://example.org/edit/first-post.atom
ETag: "c180de84f991g8"


<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<title>Atom-Powered Robots Run Amok</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<author><name>John Doe</name></author>
<content>Some text.</content>
<link rel="edit"
href="http://example.org/edit/first-post.atom"/>
</entry>

由集合创建并返回的条目可能与客户端的条目 POST 不匹配。服务器可能会更改 Entry 中各个元素的值,比如 atom: id、 atom: update 和 atom: author 值,并且可能会选择删除或添加其他元素和属性,或者更改元素内容和属性值。

输出实际上取决于所请求的内容类型。但是,至少应该将创建的资源放在 Location 中。就像后重定向获取模式。

在我的例子中,我将其保留为空白,直到另外请求为止,因为这是 JAX-RS 在使用 Response.create ()时的行为。

然而,请注意,像 Angular 这样的浏览器和框架并不会自动遵循201。我已经注意到 http://www.trajano.net/2013/05/201-created-with-angular-resource/的行为

看看 方法定义: POST

POST 方法执行的操作可能不会导致可以通过 URI 标识的资源。在这种情况下,200(OK)或204(No Content)是适当的响应状态,具体取决于响应是否包含描述结果的实体。

如果在原始服务器上已经创建了一个资源,响应应该是201(已创建) ,包含一个描述请求状态并引用新资源的实体,以及一个 Location 头(参见第14.30节)。

对于这个问题,我的另一个答案是采取务实的方法,保持 REST API 契约的简单性。在我的例子中,我重构了我的 REST API,以使事情更具可测试性,而不需要使用 JavaScript 或 XHR,只需要简单的 HTML 表单和链接。

因此,为了更具体地回答您上面的问题,我只需使用返回代码 200,并让返回的消息包含应用程序可以理解的 JSON 消息。根据您的需要,它可能需要新创建的对象的 ID,以便 Web 应用程序可以在另一个调用中获取数据。

注意,在我重构的 API 协议中,POST 响应不应该包含任何可缓存数据,因为 POST 不是真正可缓存的,所以将其限制为可以使用 GET 请求请求和缓存的 ID。

这个想法是,响应机构给你一个页面,链接到事情:

创建201

201(Created)状态代码表示请求已经完成,并且已经创建了一个或多个新资源。请求创建的主要资源由响应中的 Location头字段标识,如果没有收到 Location字段,则由有效的请求 URI 标识。

这意味着您将在响应 标题中包含一个 Location,它提供了在哪里可以找到新创建的 东西的 URL:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597

反应小组

然后他们接着提到你应该在答复 尸体中包括哪些内容:

201响应有效负载通常描述并链接到所创建的资源。

对于使用浏览器的人来说,你给他们一些他们可以看到的东西,然后点击,进入他们新创建的资源:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: text/html


Your answer has been saved!
Click <A href="/a/36373586/12597">here</A> to view it.

如果页面只能由机器人使用,那么让响应具有计算机可读性是有意义的:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/xml


<createdResources>
<questionID>1860645</questionID>
<answerID>36373586</answerID>
<primary>/a/36373586/12597</primary>
<additional>
<resource>http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586</resource>
<resource>http://stackoverflow.com/a/1962757/12597</resource>
</additional>
</createdResource>

或者,如果你愿意的话:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/json


{
"questionID": 1860645,
"answerID": 36373586,
"primary": "/a/36373586/12597",
"additional": [
"http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586",
"http://stackoverflow.com/a/36373586/12597"
]
}

答案完全取决于你,你可以随心所欲地选择你想要的答案。

缓存友好

最后还有一个优化,我可以预缓存创建的资源(因为我已经有了内容; 我只是上传了它)。服务器可以返回一个日期或 ETag,我可以存储的内容,我刚刚上传:

有关在 201响应中验证器头字段(如 ETagLast-Modified)的含义和用途的讨论,请参见 第7.2条

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/23704283/12597
Content-Type: text/html
ETag: JF2CA53BOMQGU5LTOQQGC3RAMV4GC3LQNRSS4
Last-Modified: Sat, 02 Apr 2016 12:22:39 GMT


Your answer has been saved!
Click <A href="/a/36373586/12597">here</A> to view it.

ETag s 是纯粹的任意值。当资源发生变化(并且缓存需要更新)时,让它们变得不同才是最重要的。ETag通常是一个散列(例如 SHA2-256)。但是它可以是一个数据库 rowversion,或者是一个递增的修订号。当 东西改变时,任何将 改变

简而言之:

  • 创建对象时返回 还有
  • 当一个对象被创建但是只返回它的引用时(比如一个 ID 或者一个链接) ,201