【问题标题】:REST API HTTP GET with Body带有正文的 REST API HTTP GET
【发布时间】:2020-11-21 00:36:10
【问题描述】:

实际上,我正在重写我们工作中的一些 API(在 ASP.Net Core 3.1 中),并尝试使它们成为 RESTFull。 我遇到了一些应该使用 HTTP GET 调用它的方法,因为它用于检索一些数据,但参数被包装在一个相当大的 DTO 中。

所以我问自己如何处理它:

  • 让它将 DTO 放在 URL 中,但大小有什么限制?
  • 在 HTTP GET 请求中放入正文。我进行了一些搜索,但我发现的结果很旧。显然它是允许的,但在过去不鼓励
  • 使用 HTTP Post,但不是 REST,因为应该使用 POST 来创建数据

我认为更好的解决方案是使用 HTTP Get with body(根据这篇文章https://thecodebuzz.com/http-get-delete-request-body-guidelines/ 这是可能的)

有人遇到过同样的问题吗?现在的指导方针是什么?

感谢您的意见

【问题讨论】:

  • 如果你有一个类似 seach 的端点,它接受很多参数,只需将其设为 POST。如果您不这样做,并且您无法将您的服务称为“完全 REST”,会发生什么?没有人会在意。
  • 这能回答你的问题吗? HTTP GET with request body
  • @Zinov 我已经读过这篇文章,但自从它是 11 年前写的我不确定它仍然是相关的@CodeCaster 我知道这没什么大不了的,但作为一个年轻的程序员当我没有编码的坏习惯时,我想学习尽可能多的最佳实践
  • @S.Martignier 围绕这个类似主题有很多问题/答案,这将创建一个不需要的新答案线程。但是回答您的部分问题时,当您在请求正文中传递某些内容时,您应该使用 Content-Type ,因为 GET 在语义上是错误的。你也可以在这里查看规范tools.ietf.org/html/rfc7231#section-3.1.1.5。此外,如果您使用 swagger 为您的 API 创建文档,openapi 的最新标准将抱怨 GET 上的正文

标签: api rest http-get


【解决方案1】:

我认为更好的解决方案是使用 HTTP Get 和 body

RFC 7231 不这么认为:

GET 请求消息中的有效负载没有定义的语义;在 GET 请求上发送有效负载正文可能会导致某些现有实现拒绝该请求。

你不能指望通用组件对身体做有用的事情。例如,caches 将使用 target-uri 作为主缓存键,并且根本不会考虑正文。所以很可能有奇怪的行为。

实际上,只有当您控制客户端、Web 服务器以及它们之间的组件时,带有主体的 GET 才会起作用。如果 that 是这种情况,您不妨使用您希望它具有的语义定义自己的 HTTP 方法。

例如,您可以查看HTTP SEARCH,看看这些语义是否更适合您正在尝试做的事情。

也就是说,如果您想在线条内着色,it is okay to use POST

POST 在 HTTP 中有许多有用的用途,包括“此操作不值得标准化”的一般用途。


它不是 REST,因为应该使用 POST 来创建数据

REST 没有定义任何类型的“创建”约束。 REST 说“使用统一接口中定义的适当方法”; HTTP 说“当没有更具体的方法适合时使用 POST”。

但是,如果您所处的环境不接受这一点……在不“违反规则”的情况下实现您想要的一种方法是考虑创建一个作为查询结果的新资源。所以我们 POST 一些信息,这些信息会与服务器控制的新 URI 相关联,然后后续尝试 GET 资源会为您提供所需的结果。

POST /foo

201 Created
Location: /c30e910e-7baa-4c31-9481-4c84c12884a1  
...Other Headers...

GET /c30e910e-7baa-4c31-9481-4c84c12884a1

200 OK
Content-Location: /c30e910e-7baa-4c31-9481-4c84c12884a1
...Other Headers...

The Answer

按照标准,你可以结合这两个想法来节省往返

POST /foo

201 Created
Location: /c30e910e-7baa-4c31-9481-4c84c12884a1  
Content-Location: /c30e910e-7baa-4c31-9481-4c84c12884a1
...Other Headers...

The Answer

从那里开始,这是一小步

POST /foo

200 OK
...Other Headers...

The Answer

【讨论】:

    【解决方案2】:

    你有很多问题,我会根据我的经验来回答。

    网址大小限制 一般没有限制,但取决于浏览器和服务器,例如 Internet Explorer 和 Edge 支持 2083 Characters

    HTTP规范提供HTTP Status Code 414,当服务器无法处理URL大小时会返回。

    .

    在 HTTP GET 中放置一个正文

    虽然技术上可行,但这不是最佳做法

    API 的目的是与其他开发者/应用程序共享,所以如果你编写一个非标准的 API,其他开发者使用它一定很难。

    .

    使用 HTTP POST 创建

    宁静是基于你的架构,而不是你将要使用的 HTTP 调用。对创建调用做出有意义的响应 (HTTP Status Code 201)

    【讨论】:

      【解决方案3】:

      今天仍然不鼓励。用于设计API定义的OAS3.0甚至不允许。

      您是否阅读过一些 REST 设计原则: Hackernoon 或风格指南Adidas API guide ?

      它们将帮助您走上 RESTful 之路。如果您有需要过滤的“集合资源”,请使用查询参数,如果它真的很复杂,那么它是否是搜索,在这种情况下通过“控制器资源”发布正文。

      如果您想提供有关用例的更多详细信息,这里的窥视者将很乐意提供帮助。

      【讨论】:

      • 感谢您的回答。关于 OAS3,你能指出我说他们不允许的部分吗?因为当我进行一些研究时,我发现这个 PR github.com/OAI/OpenAPI-Specification/pull/2117 允许 GET 的正文 对于 POST 描述中的 Hackernoon 文章,他们说这是为了创建数据(我知道),后来在文章中他们说,如果GET 请求作为一个太长的 URL 使用 POST 太奇怪了你能告诉我更多关于“通过控制器资源发布正文”的信息吗?我不明白这是什么意思
      • 您好,非常欢迎您。我只是在将旧 API 蓝图导入 OAS3 时才发现它,并被警告它不支持带有 GET 的主体,它在此页面上从 SwaggerHub swagger.io/docs/specification/describing-request-body 引用,关于发布到将用于搜索事物的控制器(这些是唯一应该在其名称中包含动词的资源)阅读其中的命名约定restfulapi.net/resource-naming。您的链接很有趣,尽管他们将其合并为 OAS 3.0.1!仍然气馁
      【解决方案4】:

      Voice 已经提到了与 REST 相关的大部分内容,例如

      • 如果其他方法不够用,请使用 POST
      • 在您完全控制环境时使用自定义方法(即每个客户端、服务器和中介都由您运行)

      然而,应该始终小心对待后一个,因为一旦您让外部同行进入这个环境,他们也需要定制。

      请将此帖子视为对 Voice 帖子的某种补充,因为他的帖子 IMO 缺少 REST 架构中经常使用的重要设计理念:服务器应该告诉客户端他们需要采取下一步行动!

      在 HTML 中,我们都熟悉 Web forms 以及如何使用它们来教客户资源支持的属性。但是这些形式还告诉客户端将请求发送到哪里,使用哪个 HTTP 操作,并且大多数隐含地给出了在发送实际请求之前用于将数据编组到的媒体类型。尽管大多数所谓的 REST API(其行为确实像经典的 RPC 那样)甚至根本不考虑类似形式的表示,尽管存在一些草案,例如 hal-formshalo+formsion

      引入描述资源支持的属性的中间层的优势在于,这种表示本质上是可缓存的,因为它可能不会经常更改。如果发生修改,则会对该表单资源执行不安全的操作,这会导致相应 URI 的任何存储表示无效。这样,客户还可以即时了解某个资源支持和期望的新属性或更新属性,因此不需要任何外部文档。

      这种表单资源的产品资源可以进一步存储,并赋予一个有意义的名称以供以后使用,例如desired view。该资源本质上将封装所有请求参数,例如查询词或字段。客户端现在可以简单地针对这个预先存储的查询发出 GET 请求,以检索其结果。这样做时,该查询产生的任何响应都可以再次缓存,因此符合 REST 架构提出的任何约束。

      这也与 Fielding 的说法密切相关,即 REST 架构通常比域对象拥有更多的资源。除了持有或多或少的业务对象数据的实际资源外,您还有一个表单资源,它可以教客户一个请求的外观,并且可能是一个存储所有请求参数以供最后使用的资源。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-02
        • 1970-01-01
        • 2015-10-19
        • 1970-01-01
        • 2018-11-30
        相关资源
        最近更新 更多