我正在设计一个 API 来通过 HTTP,我想知道使用 HTTP POST 命令(但仅使用 URL 查询参数而不使用请求正文)是否是一个好方法。

注意事项:

  • “良好的网页设计”需要通过 POST 发送非幂等操作。这是一个非幂等操作。
  • 当 URL 中存在请求参数时,开发和调试此应用程序会更容易。
  • 该 API 不适合广泛使用。
  • 似乎发出没有正文的 POST 请求需要更多的工作,例如A Content-Length: 0 必须显式添加标头。
  • 在我看来,没有正文的 POST 有点违背大多数开发人员和 HTTP 框架的期望。

通过 URL 查询而不是请求正文在 POST 请求上发送参数是否还有更多的陷阱或优点?

编辑:考虑这一点的原因是这些操作不是幂等的,并且除了检索之外还有副作用。看 HTTP 规范:

特别是,该公约已经 确定 GET 和 HEAD 方法不应具有 采取行动的意义 其他 比检索。这些方法应该 被认为是“安全的”。这允许用户 代理来表示其他方法, 例如 POST、PUT 和 DELETE,在 特殊方式,让用户被做成 意识到可能的事实 正在请求不安全操作。

...

方法还可以具有“愿意”的属性(除了错误或到期问题外)n> 0相同请求的副作用与单个请求相同。GET、HEAD、PUT 方法 和 DELETE 共享此属性。也 OPTIONS 和 TRACE 方法应 没有副作用,所以 本质上是幂等的。

有帮助吗?

解决方案

如果您的操作不是幂等的,那么您 必须 使用 POST. 。如果你不这样做,你只是自找麻烦。 GET, PUTDELETE 方法是 必需的 是幂等的。想象一下,如果客户端预取所有可能的内容,您的应用程序中会发生什么 GET 请求您的服务——如果这会导致客户端可见的副作用,那么就有问题了。

我同意发送 POST 有查询字符串但没有正文似乎很奇怪,但我认为在某些情况下它可能是合适的。

将 URL 的查询部分视为对资源的命令,以限制当前请求的范围。通常,查询字符串用于排序或过滤 GET 请求(如 ?page=1&sort=title)但我认为这是有道理的 POST 也限制范围(也许像 ?action=delete&id=5).

其他提示

大家都说得对:对于非幂等请求,坚持使用 POST。

同时使用 URI 查询字符串和请求内容怎么样?嗯,它是有效的 HTTP(参见注释 1),所以为什么不呢!

这也是完全合乎逻辑的:URL(包括其查询字符串部分)用于 定位 资源。而 HTTP 方法动词(POST - 及其可选请求内容)用于指定操作,或者 做什么用 资源。这些应该是正交的关注点。(但是,对于 ContentType=application/x-www-form-urlencoded 的特殊情况,它们并不是完美的正交问题,请参阅下面的注释 2。)

注1:HTTP 规范 (1.1) 并未规定查询参数和内容对于接受 POST 或 PUT 请求的 HTTP 服务器是互斥的。所以任何服务器都可以自由地接受两者。IE。如果您编写服务器,则没有什么可以阻止您选择接受两者(除了可能不灵活的框架)。一般来说,服务器可以根据它想要的任何规则解释查询字符串。它甚至可以用引用其他标头(例如 Content-Type)的条件逻辑来解释它们,这导致了注释 2:

笔记2:如果一个 网页浏览器 是人们访问您的 Web 应用程序的主要方式,并且 应用程序/x-www-form-urlencoded 是他们发布的内容类型,那么你 应该 遵循该内容类型的规则。application/x-www-form-urlencoded 的规则更加具体(坦率地说,不寻常):在这种情况下,您必须将 URI 解释为一组参数,而不是资源位置。[这与Powerlord提出的有用点相同;使用 Web 表单将内容发布到您的服务器可能很困难。只是解释有点不同。]

注3:查询字符串最初的用途是什么?RFC 3986 将 HTTP 查询字符串定义为 URI 部分,作为定位资源的非分层方式。

如果提出这个问题的读者想问什么是好的 RESTful 架构:RESTful 架构模式不需要 URI 方案以特定方式工作。RESTful 架构关注系统的其他属性,例如资源的可缓存性、资源本身的设计(它们的行为、功能和表示)以及是否满足幂等性。或者换句话说,实现与HTTP协议及其HTTP方法动词集高度兼容的设计。:-)(换句话说,RESTful 架构对于资源的使用方式并不是很明确 位于.)

最后说明:有时查询参数还用于其他用途,既不定位资源也不编码内容。见过像“PUT=true”或“POST=true”这样的查询参数吗?这些是针对不允许您使用 PUT 和 POST 方法的浏览器的解决方法。虽然这些参数被视为 URL 查询字符串(在线)的一部分,但我认为它们不是 URL 查询的一部分 在精神上.

你想要理由吗?这是一个:

Web 表单不能用于向混合使用 GET 和 POST 的页面发送请求。如果将表单的方法设置为 GET,则所有参数都位于查询字符串中。如果将表单的方法设置为 POST,则所有参数都在请求正文中。

来源:HTML 4.01 标准,部分 17.13 表格提交

从编程的角度来看,对于客户端来说,它正在打包参数并将它们附加到 url 上,然后进行 POST 与 URL 的比较。获取。在服务器端,它评估来自查询字符串的入站参数而不是发布的字节。基本上就是洗一洗。

可能存在优点/缺点的地方可能在于特定客户端平台如何使用其网络堆栈中的 POST 和 GET 例程,以及 Web 服务器如何处理这些请求。根据您的实施情况,一种方法可能比另一种更有效。了解这一点将指导您在这里做出决定。

尽管如此,从程序员的角度来看,我更喜欢允许在正文中使用包含所有参数的 POST,或者在 url 上使用包含所有参数的 GET,并在任何 POST 请求中显式忽略 url 参数。它避免了混乱。

我认为,使用查询参数来识别 URL 上的资源,同时将内容负载限制在 POST 正文中,仍然是相当 RESTful 的。这似乎将“我发送了什么?”和“我把它寄给谁?”的考虑分开了。

休息 阵营有一些指导原则,我们可以用它们来标准化我们使用 HTTP 动词的方式。当您构建 RESTful API 时,这非常有用。

简而言之:GET 应该是只读的,即对服务器状态没有影响。POST 用于在服务器上创建资源。PUT 用于更新或创建资源。DELETE 用于删除资源。

换句话说,如果您的 API 操作更改了服务器状态,REST 建议我们使用 POST/PUT/DELETE,而不是 GET。

用户代理通常知道执行多个 POST 是不好的,并且会发出警告,因为 POST 的目的是改变服务器状态(例如,在结帐时支付商品费用),您可能不想这样做两次!

与 GET 相比,您可以根据需要经常执行(幂等)。

我同意 - 如果您只是在 URL 中而不是在正文中传递数据,那么使用 GET 请求可能更安全。看 这个类似的问题 有关整个 POST+GET 概念的一些其他观点。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top