使用 POST 代替 GET 的 REST API

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

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

可以说我可以将它与 POST 查询一起使用吗?

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

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

248748 次浏览

如果没有使用这些方法分别构建 POSTGET来调用,则不能使用 API。比如你的 API 说

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

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

通常在 POST方法中,你需要发送具有指定格式的内容在主体中,这在 content-type标头中描述。用于 json 数据的 application/json

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

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

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

比如说,

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

  • POST 是对后端进行结构化,以“创建”URL 中指向的“类型”的资源。 您可以在 POST 调用的主体中使用参数或其他数据来补充 POST 操作

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

这个 维基可能会有帮助进一步澄清了一些事情。

希望这有帮助!

Just to review, REST has certain properties that a developer should follow in order to make it RESTful:

什么是 REST?

根据维基百科:

REST 体系结构样式描述了以下六个约束 应用于体系结构,同时保留 可自由设计的独立部件:

  • 客户机-服务器: 服务器不关心用户界面或用户状态,因此服务器可以更简单和更可伸缩。
  • Stateless: The client–server communication is further constrained by no client context being stored on the server between requests.
  • 可缓存的: 响应必须隐式或显式地将自己定义为可缓存的,或者不可缓存的,以防止客户机在响应进一步请求时重用过时或不适当的数据。
  • 分层系统: 客户端通常无法判断它是直接连接到终端服务器,还是连接到中间层。中间服务器可以通过启用负载平衡和提供共享缓存来提高系统的可伸缩性。
  • 按需编码(可选) : 服务器可以通过传输可执行代码临时扩展或定制客户端的功能。
  • Uniform interface: The uniform interface between clients and servers, discussed below, simplifies and decouples the architecture, which enables each part to evolve independently. (i.e. HTTP GET, POST, PUT, PATCH, DELETE)

动词应该做什么

因此,用户 丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔 · 瓦萨洛丹尼尔在问题 理解 REST: 动词、错误代码和身份验证中很好地阐述了这些方法的职责:

When dealing with a Collection URI like: http://example.com/resources/

GET: 列出集合的成员,包括它们的成员 URIs for further navigation. For example, list all the cars for sale.

PUT: 意思是“用另一个集合替换整个集合 收藏品」。

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

删除: 意思是“删除整个集合”。

回答你的问题:

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

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

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

附注: 关于 POST是否也应该被允许用于更新资源还存在一些争议... ... 虽然我不是在评论,我只是告诉你一些人对这一点有一个问题。

好好想想。当您的客户机向 URI X 发出 GET 请求时,它对服务器说的是: “我想要一个位于 X 的资源的表示,这个操作不应该改变服务器上的任何东西。”一个 PUT 请求说: “我希望您用我在这个请求的主体上给您的新实体替换位于 X 的资源”。一个 DELETE 请求说: “我要你删除位于 X 的任何资源”。PATCH 表示“我给出了这个 diff,您应该尝试将它应用到 X 处的资源,并告诉我它是否成功。”但是一个 POST 说: “我将这个从属于 X 资源的数据发送给您,我们之前已经就如何使用它达成了一致。”

如果没有文档说明资源期望 POST 并对其进行某些操作,那么向它发送 POST 并期望它像 GET 一样工作是没有意义的。

REST 依赖于底层协议的标准化行为,而 POST 恰恰是用于非标准化操作的方法。GET、 PUT 和 DELETE 请求的结果在标准中有明确的定义,但 POST 没有。POST 的结果从属于服务器,所以如果没有文档说明您可以使用 POST 来执行某些操作,那么必须假设您不能。

我使用 POST 主体来处理任何重要的和业务范围内的应用程序,原因如下:

  1. 安全性——如果我们将 GET 与查询字符串和 https 一起使用,查询字符串可以保存在服务器日志中,并作为引用链接转发。现在,服务器/网络管理员和用户离开应用程序后访问的下一个域都可以看到它们。因此,如果我们发送一个包含机密 PII 数据的查询,如客户的姓名,这可能是不希望的。
  2. URL 最大长度——这不是什么大问题,但是有些浏览器对长度有限制。因此,如果我们有几个项目在我们的网址,如查询,分页,字段返回等..。
  3. 默认情况下不缓存 POST。有人说需要缓存; 但是,在缓存超时之前,对于那个确切客户的确切对象的完全相同的搜索标准集究竟有多少次发生?

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

It is nice that REST brings meaning to HTTP verbs (as they defined) but I prefer to agree with Scott Peal.

下面是 WIKI 对 POST 请求的详细解释:

有时候 HTTPGET 甚至不太适合数据检索。这方面的一个例子是需要在 URL 中指定大量数据。浏览器和 Web 服务器可以对它们处理的 URL 的长度进行限制,而不会出现截断或错误。URL 和查询字符串中保留字符的百分号编码可以显著增加它们的长度,虽然 Apache HTTP Server 可以处理一个 URL 中的多达4000个字符,但任何 URL 中的[5] Internet Explorer 限制为2048个字符。[6]同样,HTTP GET 不应该用于敏感信息,如用户名和密码,必须与其他数据一起提交请求才能完成。即使使用 HTTPS,防止数据在传输过程中被拦截,浏览器历史记录和网络服务器的日志很可能包含明文的完整 URL,如果任何一个系统被黑客攻击,这可能会暴露。在这些情况下,应该使用 HTTPPOST。[7]

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

POST is valid to use instead of GET if you have specific reasons for doing so and process it properly. I understand it's not specifically RESTy, but if you have a bunch of spaces and ampersands and slashes and so on in your data [eg a product model like Amazon] then trying to encode and decode this can be more trouble than it's worth instead of just pre-jsonifying it. Make sure though that you return the proper response codes and heavily comment what you're doing because it's not a typical use case of POST.

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

As Scott had nicely laid out in his answer earlier, there are many good reasons to POST input data. IMHO it should be done this way, if quality of solution is the top priority.

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