REST可以在POST之后返回内容吗?


88

我正在使用RESTlet,并且已经创建了资源。我通过覆盖acceptRepresentation方法处理POST 。

客户端应向我发送一些数据,然后将其存储到数据库,将响应设置为201(SUCCESS_CREATED),我需要向客户端返回一些数据,但返回类型acceptRepresentationvoid

就我而言,我需要返回一些标识符,以便客户端可以访问该资源。

例如,如果我有一个带有URL的资源,/resource并且客户端发送了POST请求,则在DB中添加一个新行,其地址应为/resource/{id}。我需要发送{id}

难道我做错了什么?REST原则是否允许在POST之后返回某些内容?如果可以,我该怎么办?如果不能,该如何处理?


有关如何从acceptRepresentation()中设置响应正文的信息,请参见Thom的答案。
Avi Flax

Answers:


96

REST只是说您应该遵循统一接口。换句话说,它说您应该按照HTTP规范执行POST应该执行的操作。这是相关规范中的报价,

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

从中可以看到,您可以在两个地方向客户端指示新创建的资源所在的位置。Location标头应具有指向新资源的URL,并且您还可以返回包含详细信息的实体。

我不确定覆盖acceptRepresentation()和覆盖post()之间有什么区别,但是示例显示了如何从POST返回响应。


2
@ del-boy:有关如何在acceptRepresentation()中设置响应正文的信息,请参见Thom的答案。
Avi Flax

1
HTTP规范引用不禁止响应,如果您在第6节中很清楚地看到:允许: Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code. An entity consists of entity-header fields and an entity-body, although some responses will only include the entity-headers.
MikeF

@MikeF我不是要推断不允许响应主体。我引用的规范部分明确指出“并包含一个实体”。我的文字应该更加清楚。
Darrel Miller

16

我不想在响应的正文中发送任何内容。只需将Location:设置为新创建资源的(完整)URL。

您的描述表明这正是您的语义:

  1. 发布一个东西来创建它
  2. 做出足够的反应以了解两件事:
    1. 创造发生了(201)
    2. 在哪里找到新事物(Location标头)

其他都是多余的。


这并不是说维基百科始终是一个很好的来源,但认为还声称“[...]提供关于新创建资源的位置信息。在这种情况下,Location头应与201或202的HTTP状态代码发送。”
Arjan

1
POST可以执行创建一个或多个资源的逻辑。客户端可能需要处理结果。因此,在响应中返回它避免了对API进行一个或多个GET调用的需要。通过POST方法创建/更改的数据对于客户端可能不是(而且通常不是)多余的。
Paulo Merson

10

两个不同的问题:

REST应用程序模式是否支持在POST中返回数据?

我不认为REST明确禁止这样做,但是Darrel的回答中阐明了首选的处理方法。

RESTlet框架是否允许在POST中返回数据?

是的,即使它返回void,在扩展Resource的类中,您也可以通过getResponse()方法完全访问Response对象。因此,您可以使用所需的任何数据调用getResponse()。setEntity()。


6

以任何要求的格式输出。可能是:

<success>
    <id>5483</id>
</success>

要么:

{ "type": "success", "id": 5483 }

这取决于您通常执行的操作。如果他们不期望数据,则应该忽略它,但是任何想要正确处理它的客户端都应该能够。


好的,我有两种可能的格式(html和xml)。我知道如何处理所请求格式的类型,但是我不知道如何向响应中添加数据。代表方法返回代表,所以我只返回我想要的东西,但是acceptRepresentation是空方法,所以我不能返回任何数据……
del-boy

1

如果您响应201用实体主体创建,而不是位置重定向,则最好包含一个Content-Location标头,该标头指向响应中表示的资源。

这将避免潜在的混乱-客户可以(合理地)假设响应实体实际上代表“创建者”的新状态,而不是所创建的资源。

> POST /collection
> ..new item..

< 201 Created
< Location: /collection/1354
< Content-Location: /collection/1354
< <div class="item">This is the new item that was created</div>

3
我认为Content-Location的用途不同。HTTP规范说未为POST和PUT定义Content-Location。Location标头与201-Create一起使用。返回位置并不会自动进行重定向,因此您需要输入3XX的响应代码。
Darrel Miller

1
位置标头用于(在201响应中)指示所创建资源的位置;它与响应所伴随的实体无关。我的意思是-如果您想在201响应本身中包含创建的资源(而不是将客户端重定向/重定向到另一个URI),那么内容位置标头将是一个好主意。这可能有点“违反规则”,但是比要求另一个请求/响应周期将新资源的状态发送给客户端要更有效。
迈克,

对我来说有意义。我以前从未使用过Content-Location标头。
Darrel Miller

如果客户端是具有浏览器的人员,则返回带有Location标头的201没有任何意义。用户将不知道该怎么办。如果客户是机器人,则可以对其编程以知道如何处理它-就像位置上的后续GET一样。
无可争议的

3
@irreputable:我相信REST是用于设计API的,其中A并不代表需要一些HTML呈现的用户代理。
爱马仕(Hermes)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.