GET 用于复杂负载情景吗?

huangapple go评论93阅读模式
英文:

GET for complex payload scenarios?

问题

我们的团队正在设计一个严格遵循REST约定的RESTful API。我们目前面临一个具有挑战性的问题,我们还没有找到解决方案。正如您所看到的,GeneratePermissionUrls方法应该是一个GET请求,而不是POST,因为它用于检索数据。它可能会创建一些用于上传文件的临时URL,但我不认为这会使这个方法成为POST,对吗?我们不得不将其更改为POST的原因是参数包含一个ICollection<AnimalGeneratePermissionUrlsFileInfoDTO>,这只能在HTTP Body中支持,GET不支持。您有任何建议吗?

英文:

Our team is designing a RESTful API that strictly follows REST conventions. We are currently facing a challenging problem for which we have not yet found a solution. As you can see, the
GeneratePermissionUrls
method should be a GET request instead of a POST because it retrieves data. It may create some temporary URLs for uploading files, but I don’t think that would make this method a POST, right? The reason we had to change it to a POST is that the parameters contain an
ICollection<AnimalGeneratePermissionUrlsFileInfoDTO>
, which is only supported in the HTTP Body, something that GET does not have. Do you have any suggestions?

    [HttpPost]
    [ProducesResponseType(201)]
    [ProducesResponseType(400)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task&lt;IActionResult&gt; GeneratePermissionUrls(AnimalGeneratePermissionUrlsParameters parameters, CancellationToken cancellationToken = default)
    {
        var result = await animalService.GenerateSASUrls(parameters.FilesInfo, parameters.AnimalId, parameters.ClientUploadSpeed, parameters.ClientInternetLatency, nameof(AnimalsController));
        return result.Match&lt;IActionResult&gt;(
                       success =&gt; Ok(success.AttachedData),
                       error =&gt; NotFound(error));
    }
using System.ComponentModel.DataAnnotations;

namespace petaverseapi;

public class AnimalGeneratePermissionUrlsParameters
{
    [Required]
    public int AnimalId { get; set; }

    [Required]
    public double ClientUploadSpeed { get; set; }

    [Required]
    public int ClientInternetLatency { get; set; }

    public ICollection&lt;AnimalGeneratePermissionUrlsFileInfoDTO&gt; FilesInfo { get; set; } = null!;
}

public class AnimalGeneratePermissionUrlsFileInfoDTO
{
    public string FileName { get; set; } = string.Empty;
    public float FileSize { get; set; }
}

I was trying to make my action controller is a GET request.

答案1

得分: 1

GeneratePermissionUrls 方法应该是一个 GET 请求,而不是一个 POST 请求,因为它是用于检索数据的。它可能会创建一些用于上传文件的临时 URL,但我认为这不应该使这个方法变成 POST,对吗?

如果请求的语义是安全的(也就是基本上只读),那么使用GET是合适的。这相当于说:“从你的文档存储中获取这个文档给我”。

但这假设你可以将所有需要的信息编码到目标资源标识符中。

在那些需要查看请求有效负载的情况下,已注册的 解决方案是使用POST(遗憾的是,这会隐藏掉通用应用程序组件的请求基本上是只读的信息)。

POST 的一个备选方案是使用 QUERY,它适用于需要在请求中包含正文的情况。你可以在这里找到最新的草案git 存储库的问题跟踪器会提供额外的细节,以便你判断你的请求的语义是否适合这个方法令牌。

对我来说?如果需要正文,我会使用POST,我不是测试飞行员,而且一个没有注册的方法令牌,带有已过期的草案规范,吸引力不大。


但是,我可能会反对认为在这里需要一个正文的假设。

我们不得不将其更改为 POST 的原因是参数包含 ICollection,而这仅在 HTTP 正文中受支持,GET 不具备这个功能。

听起来你正在使用实现限制来规定你的 API,这…嗯,这是一个选择,根据你的本地上下文中权衡的价值,这甚至可能是正确的选择。

我在这里的数据类中没有看到任何东西,不能通过 URI 模板来描述(假设 URI 长度的实际限制不会影响结果),这将允许你从资源标识符复制你想要的信息到你的内存表示中。
你可能需要自己编写解析代码,包括在存在不良/恶意数据的情况下可能发生的各种错误处理。

在某些情况下,甚至可以实现两个处理程序 - 一个用于常见情况(假设在常见情况下 URL 长度是合理受限制的),另一个用于处理异常情况。

英文:

> the GeneratePermissionUrls method should be a GET request instead of a POST because it retrieves data. It may create some temporary URLs for uploading files, but I don’t think that would make this method a POST, right?

GET is appropriate if the semantics of the request are safe (aka: essentially read only). It's analogous to "get me this document out of your document store".

But that assumes that you can encode into the target resource identifier all of the information you need.

In those cases where you are looking at the request payload as well -- the registered solution is POST (which, sadly, hides from general purpose application components the information that the request is essentially read only).

A candidate alternative to POST is to use QUERY, which is intended for those circumstances in which you want a safe request with a body. You can find the most recent draft here; the issue tracker at the git repository will give you additional details, so that you can judge whether the semantics of your request are (or can be adapted to be) suitable for this method token.

Me? If a body were necessary, I would use POST -- I'm not a test pilot, and an unregistered method token with an expired draft specification has little appeal.


But I might push back on the assumption that a body is necessary here.

> The reason we had to change it to a POST is that the parameters contain an ICollection , which is only supported in the HTTP Body, something that GET does not have.

It sounds like you are using implementation limitations to dictate your API, which... well, it's a choice, and it could be even be the right choice, depending on the value of tradeoffs in your local context.

I don't see anything in the data classes here that couldn't be described by a URI template (assuming that de facto limits on URI length don't interfere with the result), which would allow you to copy the information you want from the resource identifier to your in-memory representation.

You might have to write the parsing code yourself, including handling the various errors that could occur in the presence of bad/malicious data.


In some cases, it could even make sense to implement two handlers - one for common cases (assuming that in the common cases the URL length is reasonably bounded) and other to handle the outliers.

huangapple
  • 本文由 发表于 2023年7月20日 21:28:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76730402.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定