RESTful 'PUT'操作是否应该返回某些内容...

9 浏览
0 Comments

RESTful 'PUT'操作是否应该返回某些内容...

我想知道人们对于返回空(null)响应体的RESTful PUT操作有什么看法。

0
0 Comments

如果REST API的后端是SQL关系数据库,则需要在可以更新的每个记录中添加RowVersion(以避免丢失更新问题)。

在PUT操作之后,应始终返回记录的新副本以获取新的RowVersion。

如果您不关心丢失的更新,或者希望强制客户端在PUT之后立即进行GET,则不要从PUT返回任何内容。

在使用RESTful API进行PUT操作时,有时会出现一个问题:PUT操作是否应该返回一些东西?这个问题的出现主要是因为如果后端是SQL关系数据库,为了避免丢失更新的问题,需要在每个可以更新的记录中添加RowVersion,并且在PUT操作后需要返回新的记录副本以获取新的RowVersion。但是,如果不关心丢失的更新,或者希望强制客户端在PUT之后立即进行GET,则可以不返回任何内容。

解决这个问题的方法就是根据具体需求来决定是否返回内容。如果需要避免丢失更新问题或者需要获取新的RowVersion,就应该返回新的记录副本。如果不关心丢失的更新或者希望强制客户端在PUT之后立即进行GET,就可以不返回任何内容。

以下是一个示例代码,演示了如何在PUT操作中返回新的记录副本:

@app.route('/api/user/', methods=['PUT'])
def update_user(user_id):
    # 获取要更新的用户记录
    user = User.query.get(user_id)
    # 更新用户记录
    user.name = request.json['name']
    user.email = request.json['email']
    # 提交数据库更新
    db.session.commit()
    # 返回新的用户记录副本
    return jsonify(user.serialize())

在上述示例代码中,PUT操作更新了用户记录,并在数据库提交更新后返回了新的用户记录副本。

总之,是否应该在RESTful API的PUT操作中返回内容取决于具体需求。如果需要避免丢失更新问题或者需要获取新的RowVersion,应该返回新的记录副本。如果不关心丢失的更新或者希望强制客户端在PUT之后立即进行GET,则可以不返回任何内容。

0
0 Comments

RESTful 'PUT'操作是否应该返回一些内容?

这个问题的出现是因为HTTP规范(RFC 2616)中有一些相关的建议。根据我的解读,以下是我的观点:

- 对于成功更新已有资源的PUT操作,应该返回HTTP状态码200 OK。不需要返回响应体。(根据RFC 2616第9.6节,204 No Content更加合适。)

- 对于成功创建新资源的PUT操作,应该返回HTTP状态码201 Created,并在Location头字段中返回新资源的最具体URI,同时在响应体中返回其他相关的URI和资源的元数据。(RFC 2616第10.2.2节)

- 对于由于第三方修改而导致的未成功PUT操作,应该返回HTTP状态码409 Conflict,并在响应体中返回尝试更新和当前资源之间的差异列表。(RFC 2616第10.4.10节)

- 对于未成功的PUT操作,应该返回HTTP状态码400 Bad Request,并在响应体中返回自然语言文本(如英语),解释PUT操作失败的原因。(RFC 2616第10.4节)

需要注意的是,当我写这个答案时,RFC 2616是最新的规范,但是该RFC已被新版取代。在引用任何标准时,验证使用的是否是最新版本通常很有用。

有趣!Mozilla这样做似乎有些傲慢,因为我在RFC 2616中找不到任何明确禁止将200用于PUT、DELETE或任何其他方法的规定(特别是第10.2节Successful 2xx和10.2.1节200 OK)。我有什么遗漏了吗?难道是Mozilla成了W3和IETF的老板?;)或者他们可能从未听说过波斯特尔的鲁棒性原则。

好的,该句话于2013年2月3日被删除。可能是因为有人在这里读到了这个信息。;)

PUT方法的语义是忽略资源的当前状态,因此仅当请求是有条件的时,才有意义返回409冲突的响应,表示PUT操作未成功。

如果看一下RFC链接,它解释了(或多或少地)为什么对PUT操作返回409响应。虽然它没有明确说明“有条件的”,但它说“如果正在使用版本控制”,我推断这是一回事。

很好的答案。一个小小的建议:如果你不打算返回响应体以表示成功的操作,我建议只使用204。某些客户端(例如jQuery Ajax)会因为期望非零长度的响应但未收到而出错。你可以在这个问题中看到一个例子。

RestAPITutorial.com还建议在PUT请求成功时返回200 OK。

你可能需要至少返回服务器上新创建资源的ID。否则,客户端无法知道创建了哪个实体。

我的回答的第二个要点正好涵盖了如何以与HTTP规范一致的方式做到这一点。

为什么要在响应中使用Location头字段返回新资源的URI?客户端已经知道了,因为它已经向同一个URI进行了POST请求。

POST意味着“创建”,这意味着一个不带有实体UID的URI。因此,您不会知道生成的实体,您只是发送要创建的内容,但是您不知道它将具有哪个UID。这就是为什么您应该以某种方式响应新创建实体的位置(或UID)。

如果PUT操作导致更新资源,我想返回{ "status":"ok", "modified":true }。如果请求有效负载没有变化,则返回{ "status":"ok", "modified":false }。后一种情况是指在请求有效负载没有变化的情况下,后续的PUT操作没有导致指定资源的更改。由于PUT应该是幂等的,我不知道是否根据规范允许这样做。还有其他什么可以用来表示PUT操作没有导致更新的?我不想使用40x的值,因为那会暗示错误。

实际上,我建议在使用PUT时将资源的状态(如版本)返回给客户端,这样客户端就不需要发送获取资源的请求。

可能RFC2616已经更新,因为在9.6中并没有提到与200相关的“不需要响应体”的内容。实际上,在与PUT相关的内容中根本没有提到响应体。它只说“如果修改了现有资源,则应发送200(OK)或204(No Content)响应代码以指示请求成功完成。”

我建议添加HTTP 422 Unprocessable Entity。它有助于区分“错误请求”(例如格式不正确的XML/JSON)和无效的字段值。

“HTTP状态码400 Bad Request用于未成功的PUT”,我猜规范已经更新,因为它没有这样说,也没有关于PUT的任何其他内容,除非在某些情况下使用409。

可以将此方法扩展为允许使用类似于Postgresql中SQL UPDATE的RETURNING子句的查询参数,以指示是否以及返回什么。

波斯特尔的鲁棒性原则也有批评意见。

请注意:“该文档已被取代。在2014年,RFC2616被多个RFC(7230-7237)取代。有关更多信息,请参见IETF文档。”

多么令人高兴地听到标准已经进步了!如果在此期间有人受到了我在这里的答案鼓励去阅读它们,那就更令人高兴了。然而,我现在不确定是否可以编辑这个答案,或者是否应该编辑。根据这里的问答格式,也许创建并投票支持基于最新规范的单独答案可能是最好的?

如果你问我,编辑问题以留下一个注释,说明RFC已经被取代,就像在这个元回答中建议的那样,不会有害。正如你所说,最近的规范可能更适合一个新的答案。

0
0 Comments

PUT操作是否应该返回更新后的资源呢?这个问题的出现是因为当客户端向服务器发送资源表示时,服务器可以对该资源应用一些处理,因此客户端希望在请求成功完成后知道这个资源的样子(否则就需要发出另一个GET请求)。

REST不要求在PUT中更新整个资源,尽管这通常是推荐的。一些字段可能没有意义进行更新,比如创建日期或最后修改日期,这些字段可能不会包含在PUT请求的主体中,但是可能会因为PUT而发生变化。然而,我不同意LiorH的观点,认为PUT应该返回资源;我认为应该在PUT后执行GET以获取更新后的资源。

“REST不要求在PUT中更新整个资源”这个说法是否应该属于PATCH操作?是的,我同意并撤回我之前的评论。我改变了对REST和PUT的看法——PUT应该始终是幂等的,不应该用于部分更新。除非支持PATCH,否则POST是唯一的替代方法。然而,PATCH是一个新的动词,可能不被一些服务器端框架支持。

这个答案写在rfc7231之前,但第4.3.4节明确指出“PUT方法请求使用请求消息载荷中的表示定义的状态创建或替换目标资源的状态”。

如果更新的对象很大怎么办?返回大量不太可能被使用的数据似乎是浪费。

0