使用POST而不是GET的REST API

han*_*ank 54 api rest post get

让我们假设一个服务提供了一些我可以使用的功能:

GET /service/function?param1=value1&param2=value2
Run Code Online (Sandbox Code Playgroud)

说我可以在POST查询中使用它是正确的吗?

POST /service/function { param1 : value1, param2 : value2 }
Run Code Online (Sandbox Code Playgroud)

这两个查询是否相同?我可以在任何情况下使用第二个变体,或者文档应该明确说我可以同时使用GET和POST查询吗?

Kri*_*ian 60

只是为了审查,REST开发人员应该遵循某些属性来实现它RESTful:

什么是REST?

根据维基百科:

REST架构风格描述了应用于体系结构的以下六个约束,同时使各个组件的实现可以自由设计:

  • 客户端服务器:服务器不关心用户界面或用户状态,因此服务器可以更简单,更具可伸缩性.
  • 无状态:客户端 - 服务器通信进一步受到请求之间没有客户端上下文存储在服务器上的限制.
  • 可缓存:响应必须(隐式或显式)将自身定义为可缓存,以防止客户端重用陈旧或不适当的数据以响应进一步的请求.
  • 分层系统:客户端通常无法判断它是直接连接到终端服务器,还是沿途的中介.中间服务器可以通过启用负载平衡和提供共享缓存来提高系统可伸缩性.
  • 按需代码(可选):服务器可以通过传输可执行代码来临时扩展或自定义客户端的功能.
  • 统一接口:下面讨论的客户端和服务器之间的统一接口简化和解耦了体系结构,使每个部分能够独立发展.(即HTTP GET,POST,PUT,PATCH,DELETE)

动词应该做什么

SO用户Daniel Vasallo理解REST:动词,错误代码和身份验证的问题中很好地阐述了这些方法的职责:

处理集合URI时,例如:http://example.com/resources/

GET:列出集合的成员,并使用其成员URI进行进一步导航.例如,列出所有待售汽车.

PUT:意义定义为"用另一个集合替换整个集合".

POST:在集合中创建一个新条目,集合自动分配ID.创建的ID通常作为此操作返回的数据的一部分包含在内.

DELETE:意义定义为"删除整个集合".

那么,回答你的问题:

说我可以在POST查询中使用它是正确的吗?...

这两个查询是否相同?我可以在任何情况下使用第二个变体,或者文档应该明确说我可以同时使用GET和POST查询吗?

如果您正在编写一个普通的旧RPC API调用,只要处理服务器端在两个调用之间没有区别,它们在技术上可以互换.但是,为了使调用成为RESTful,通过该GET方法调用端点应该具有不同的功能(即从资源中获取资源)POST(即创建新资源).

旁注:那里有一些关于是否也POST应该被允许用于更新资源的争论......虽然我没有对此发表评论,但我只是告诉你一些人在这一点上有问题.

  • 因此,当我们出于各种原因(URL长度限制,在许多框架中不支持GET的主体等)而要使用其他动词而不是GET来检索实体列表时,REST API规范似乎还没有准备好用于实际情况。 )。这意味着,有许多hacky,不一致的解决方案可解决此问题,而没有规范可指导开发人员。 (2认同)

小智 46

出于以下原因,我将POST主体用于任何非平凡和业务线应用程序:

  1. 安全性 - 如果我们将GET与查询字符串和https一起使用,则查询字符串可以保存在服务器日志中并作为引用链接转发.现在,服务器/网络管理员以及用户离开您的应用后访问的下一个域都可以看到这两者.因此,如果我们发送包含机密PII数据(例如客户名称)的查询,则可能不需要.
  2. URL最大长度 - 不是一个大问题,但有些浏览器的长度有限制.因此,如果我们的URL中有几个项目,如查询,分页,返回的字段等等....
  3. 默认情况下,Post不是缓存.有人说需要缓存; 但是,在缓存超时之前,确切客户的确切对象的完全相同的搜索条件是多少次?

顺便说一句,我也把字段放回到我的POST主体中,因为我可能不希望公开我的字段名称.安全就像一个洋葱; 多层次让我们哭泣!

  • 我认为Scott的观点是,通过使用POST而不是GET,您不必使用查询字符串*. (6认同)
  • 无论请求类型如何,查询字符串通常都保存在Web服务器日志中.如果您认为POST更安全,因为您无法看到某些内容,那么您就错了.缓存是完全不同的. (3认同)
  • 被否决,根据 OP 的标记方式,该问题专门针对 REST。这个答案在这种情况下无关紧要,因为它绝对不是 REST。 (3认同)

Sac*_*hin 35

您不能使用API使用,POST或者GET如果它们不构建,则使用这些方法进行调用.就像你的API说的那样

/service/function?param1=value1&param2=value2
Run Code Online (Sandbox Code Playgroud)

通过使用GET方法访问.然后,POST如果POST创建者未将其指定为方法,则无法使用方法调用它.如果你这样做,你可能会获得405 Method not allowed地位.

通常在POST方法中,您需要使用指定格式发送正文中的内容,该格式在content-type标题中描述.application/json对于json数据.

之后,请求体在服务器端被反序列化.因此,您需要从客户端传递序列化数据,并由服务开发人员决定.

但是,一般而言,GET当服务器将一些数据返回给客户端并且对服务器没有任何影响,而POST用于在服务器上创建一些资源时使用.所以一般来说它不应该是相同的.

  • 但在 GET 请求中,URL 的长度是有限的(最大 URL 长度为 2048 个字符)。因此,如果我想向具有可能是长字符串 (JSON) 的参数的 API 发送请求,我应该使用 POST 而不是 GET 吗? (2认同)

Ped*_*eck 11

想一想.当您的客户端向URI X发出GET请求时,它对服务器的说法是:"我想要一个位于X的资源的表示,并且此操作不应该更改服务器上的任何内容." 一个PUT请求说:"我希望你用我在这个请求的主体上给你的新实体替换位于X的资源." DELETE请求说:"我希望您删除位于X的资源".一个PATCH说"我给你这个差异,你应该尝试将它应用到X的资源并告诉我它是否成功." 但是一个POST说:"我正在向你发送这个从属于X的资源的数据,我们之前就你应该用它做什么达成了协议."

如果您没有在资源需要POST的地方记录它并对其执行某些操作,那么向它发送POST是没有意义的,期望它像GET一样.

REST依赖于底层协议的标准化行为,而POST恰好是用于未标准化的操作的方法.GET,PUT和DELETE请求的结果在标准中明确定义,但POST不是.POST的结果从属于服务器,因此,如果没有记录您可以使用POST执行某些操作,则必须假设您不能.


小智 6

REST给HTTP动词(按其定义)带来了意义,但我更喜欢Scott Peal。

这也是WIKI对POST请求的扩展说明中的项目:

有时HTTP GET甚至不适合数据检索。例如,当需要在URL中指定大量数据时。浏览器和Web服务器可以限制它们处理的URL的长度,而不会被截断或错误。URL和查询字符串中保留字符的百分比编码会大大增加它们的长度,而Apache HTTP Server可以处理URL中最多4,000个字符,[5] Microsoft Internet Explorer限制为任何URL中2,048个字符。[6] 同样,在必须将敏感信息(例如用户名和密码)与其他数据一起提交以完成请求的情况下,不应使用HTTP GET。即使使用HTTPS,也可以防止在传输过程中拦截数据,浏览器历史记录和Web服务器的 的日志可能包含纯文本的完整URL,如果其中任何一个系统被黑客入侵,则该URL可能会公开。在这些情况下,应使用HTTP POST。[7]

我只能建议REST团队考虑更安全地使用HTTP协议,以避免使消费者难以接受非安全的“良好做法”。

  • 与 [Scott Peal 的答案](/sf/answers/2481151081/) 相比,这并没有真正提供新的东西。您只引用了 wiki/provided 和链接,并对此进行了说明:虽然链接可以回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会变得无效。 (3认同)

小智 5

如果我正确理解问题,他需要执行 REST GET 操作,但想知道是否可以通过 HTTP POST 方法发送数据。

正如斯科特之前在他的回答中很好地阐述的那样,发布输入数据有很多充分的理由。恕我直言,如果解决方案的质量是重中之重,那么应该这样做。

不久前,我们创建了一个 REST API 来验证用户身份,获取用户名/密码并返回访问令牌。API 在 TLS 下加密,但暴露于公共互联网。在评估了不同的选项后,我们选择 HTTP POST 作为“GET 访问令牌”的 REST 方法,因为这是满足安全标准的唯一方法。