关于HTTP动词的困惑

时间:2018-10-16 17:01:43

标签: rest http asp.net-web-api

在构建Web API时,遇到了一些情况,我不确定要使用哪些HTTP动词。

  1. 下载有副作用的文件

    我的第一个想法是使用GET,但是后来我意识到,当客户端调用API下载文件时,服务器还会更新DB中的计数器,指示下载总数和上次下载日期。

    这是否违反规范?毕竟,服务器状态已更改。这不应该是POST / PUT吗?但是,如果使用POST / PUT,我将无法共享链接并从浏览器使用它。

  2. 生成随机值列表

    就我而言,我需要调用API来生成测试(考试)问题的随机列表。该请求不会更改服务器上的任何内容,它每次客户端调用它时都会产生不同的响应内容,所以我想使用GET可以。幂等仅适用于服务器状态,而不适用于传递给客户端的结果,对吗?那么是否允许重复请求(获取)具有不同结果的相同资源(从客户端看到)?

  3. 根据用户输入生成值列表

    最后一种情况与前一种情况相似。我需要服务器生成问题列表。这次基于先前测试的错误答案。同样,该请求不会更改服务器数据,但我需要(相对)将一长串项目发送到服务器,这些列表不必适合作为查询字符串。这就是为什么我认为可以使用体内有负载的POST的原因。但是说实话,这感觉很奇怪。

是否有针对每种情况使用哪些动词的明确答案?

1 个答案:

答案 0 :(得分:1)

下载有副作用的文件

  

我的第一个想法是使用GET

那是正确的答案。 HTTP方法是关于语义的,而不是实现。

  

HTTP不会尝试要求GET的结果是安全的。什么   确实要求操作的语义是安全的,并且   因此,这是实现的错误,而不是接口的错误   或该界面的用户,如果有任何结果导致   导致财产损失-Fielding (2002)

生成随机值列表

  

每次客户端调用它时,它都会产生不同的响应内容,所以我想使用GET是可以的。

是的-再说一次,只要语义safe,GET是一个不错的选择。

根据用户输入生成值列表

  

我需要(相对)将一长串项目发送到服务器,这些列表不必适合作为查询字符串。这就是为什么我认为可以使用体内有负载的POST的原因。但是说实话,这感觉很奇怪。

因此,如果您不担心标识符的长度,那么GET将是通常的答案,所有用户输入都编码为URI。

这时,您有两种选择。

最简单的方法是简单地使用POST,并在消息正文中输入用户输入,并在Response中生成结果值列表。不应感到奇怪-POST是HTTP中语义约束最少的方法。

或者,您可以重新考虑协议,以便客户端使用消息正文作为有效负载来创建“查询资源”。因此POST可以再次在这里工作,或者可以使用PUT(对URI的处理有些不同)。

第三种可能性是查看Hypertext Transfer Protocol Method Registry,以查看是否存在具有所需语义的扩展方法,请仔细注意该方法是否安全。搜索和报告可能符合您的需求。

  

如果以后再决定,我想将每个生成的测试记录到数据库,您是否建议将API更改为POST或保持原样?在更改HTTP动词的情况下,客户端不会注意到任何功能上的更改,但是会破坏API,因此从语义上来说,毕竟从一开始就使用POST更合适吗?在这两种情况下,其含义都是“创建新测试”。

不,但是稍微改变一下,事情就会变得有趣。有趣的地方并不是“记录到数据库”,而是“以后可以将其从数据库中拉出”。当您开始寻求创建新资源以供以后检索时,GET不再是理想选择。

  

它将破坏API

仅因为您忽略了重要的REST约束-REST api are hypertext driven。在网络上,我们可以通过从链接更改为表单(或从GET表单更改为POST表单)来轻松地从GET更改为POST。客户端不会播放“猜测URI”或“猜测方法”,因为状态表示包括这些详细信息。

但是,是的,如果对语义进行了足够大的更改,它将不会向后兼容。因此,不要假装它是向后兼容的-只需使用新资源创建一个新协议即可。