92

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

GET /service/function?param1=value1&param2=value2

说我可以将它与 POST 查询一起使用是否正确?

POST /service/function { param1 : value1, param2 : value2 }

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

4

8 回答 8

101

出于以下原因,我将 POST 正文用于任何重要的业务线应用程序:

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

顺便说一句,我还将要返回的字段放在我的 POST 正文中,因为我可能不希望公开我的字段名称。安全就像洋葱;它有很多层次,让我们哭泣!

于 2016-02-16T23:24:13.313 回答
74

只是为了回顾REST一下,具有开发人员应该遵循的某些属性才能实现它RESTful

什么是 REST?

根据维基百科:

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

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

动词应该做什么

SO 用户Daniel Vasallo在“ Understanding REST: Verbs, error code, and authentication ”问题中很好地阐述了这些方法的职责:

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

GET:列出集合的成员,并附上他们的成员 URI,以便进一步导航。例如,列出所有待售汽车。

PUT:含义定义为“用另一个集合替换整个集合”。

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

DELETE:含义定义为“删除整个集合”。

所以,回答你的问题:

说我可以将它与 POST 查询一起使用是否正确?...

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

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

旁注:关于是否POST也应该允许用于更新资源存在一些争论......虽然我没有对此发表评论,但我只是告诉你有些人对此有疑问。

于 2013-10-28T19:01:02.273 回答
49

您不能使用APIusingPOST或者GET如果它们不是构建来单独使用这些方法调用。就像你的 API 说

/service/function?param1=value1&param2=value2

通过 usingGET方法访问。POST如果它的创建者没有将它指定为方法,那么你不能使用方法来调用它POST。如果你这样做,你可能会得到405 Method not allowed状态。

通常在POST方法中,您需要以指定格式发送正文中的内容,该格式在content-type标头中进行了描述。application/json对于 json 数据。

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

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

于 2013-10-28T14:35:58.407 回答
17

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

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

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

于 2013-11-02T19:59:15.747 回答
14

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 服务器' s 日志可能包含纯文本的完整 URL,如果任一系统被黑客入侵,可能会暴露。在这些情况下,应该使用 HTTP POST。[7]

我只能建议 REST 团队考虑更安全地使用 HTTP 协议,以避免让消费者为不安全的“良好实践”而苦恼。

于 2017-11-01T23:46:05.770 回答
4

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

正如斯科特早些时候在他的回答中很好地阐述的那样,POST 输入数据有很多很好的理由。恕我直言,如果解决方案的质量是重中之重,就应该这样做。

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

于 2019-11-21T22:17:39.413 回答
3

在 REST 中,每个 HTTP 动词都有其位置和含义。

例如,

  • GET 是获取 URL 中指向的“资源”。

  • POST 是构造后端以“创建” URL 中指向的“类型”资源。您可以在 POST 调用的主体中使用参数或附加数据来补充 POST 操作。

在您的情况下,由于您对使用查询“获取”信息感兴趣,因此它应该是 GET 操作而不是 POST 操作。

这个wiki 可能有助于进一步澄清事情。

希望这有帮助!

于 2013-10-28T16:12:59.523 回答
3

如果您有特定的理由这样做并正确处理,则可以使用 POST 代替 GET。我知道这不是专门的 RESTy,但如果你的数据中有一堆空格、& 和斜线等 [例如,像亚马逊这样的产品模型],那么尝试编码和解码这可能比它的价值更麻烦,而不仅仅是对它进行预json化。确保您返回正确的响应代码并大量评论您正在做的事情,因为这不是 POST 的典型用例。

于 2019-10-01T13:15:21.550 回答