使用POST创build请求,响应代码200或201和内容

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

我计划发布到

http://myhost/serviceX/someResources 

假设有效,我应该使用什么响应代码? 我可能会返回哪些内容。

我正在查看HTTP响应代码的定义并查看这些可能性:

200:返回描述或包含操作结果的实体;

201:这意味着创build。 含义*请求已完成并导致创build新资源。 新创build的资源可以由响应实体中返回的URI(s)引用,其中由Location标题字段给出的资源的最具体的URI。 响应应该包括一个包含资源特性和位置的实体,用户或用户代理可以从中select一个最合适的实体。 实体格式由Content-Type头域中给出的媒体types指定。 *

后者听起来更符合Http规范,但我什么都不清楚

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

手段。

build议? 解释?

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19

这只是一个冒号定界的键值。

ETag:“xyzzy”

它可以是任何types的文本数据 – 我通常包括一个JSONstring与创build的项目的标识符。 单凭testing的便利性使其值得。

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

在这个例子中,创build项目的标识符,URI和types是“资源特性和位置”。

我认为atompub REST API是一个很好的服务的例子。 从atompub规范看下面的代码片段:

 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表示成功创build。响应包括指示primefaces条目的成员条目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> 

集合创build并返回的条目可能与客户端发布的条目不匹配。 服务器可以改变Entry中各种元素的值,如atom:id,atom:updated和atom:author值,可以select删除或添加其他元素和属性,也可以改变元素内容和属性值。

这个想法是,响应主体给你一个链接你的东西的页面:

201创build

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

这意味着您将在响应中包含一个Location ,该Location提供了可以在其中find新创build的事物的URL的URL:

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

响应体

然后他们继续提到你应该包括在响应主体中

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

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

 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" ] } 

这个回应完全取决于你。 这是任意你想要的。

caching友好

最后是我可以预先caching创build的资源的优化(因为我已经有内容,我刚刚上传)。 服务器可以返回一个date或ETag,我可以存储我刚刚上传的内容:

关于validation器头部字段(如ETag和Last-Modified)在201响应中的含义和用途的讨论见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是纯粹的任意值。 当资源发生变化(需要更新caching)时,让它们变得非常重要。 ETag通常是散列(例如SHA2)。 但它可以是一个数据库rowversion ,或一个递增的版本号。 当事情发生变化时,任何事情都会改变

检出HTTP:方法说明:POST 。

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

如果源服务器上已经创build了一个资源,那么响应应该是201(创build),并且包含一个描述请求状态的实体,并引用新资源和一个位置标题(见14.30节)。

简单来说:

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

输出实际上取决于被请求的内容types。 但是,至less应该放置在“位置”中创build的资源。 就像Post-Redirect-Get模式。

在我的情况下,我把它留空,直到另有要求。 因为这是使用Response.created()时JAX-RS的行为。

但是,请注意,像Angular这样的浏览器和框架不会自动跟随201。 我已经注意到http://www.trajano.net/2013/05/201-created-with-angular-resource/中的行为;

另一个答案我会采取务实的方法,并保持简单的REST API合同 。 在我的情况下,我重构了我的REST API,使得事情更加可testing,而不诉诸于JavaScript或XHR,只是简单的HTML表单和链接。

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

值得注意的是,在我重构的API合约中,POST响应不应包含任何可caching的数据,因为POST不是真正可以caching的,因此将其限制为可以使用GET请求进行请求和caching的ID。