使用一长串查询参数设计RESTful查询API

mis*_*E46 137 api rest http-parameters

因此,我需要设计一个RESTful查询API,它基于一些过滤器返回一组对象.通常的HTTP方法是GET.唯一的问题是,它可以拥有至少十几个过滤器,如果我们将所有这些过滤器作为查询参数传递,则URL可能会变得很长(足够长以被某些防火墙阻止).

减少参数数量不是一种选择.

我能想到的另一种选择是在URI上使用POST方法并将过滤器作为POST主体的一部分发送.这是不是RESTfull(对查询数据进行POST调用).

有没有更好的设计建议?

谢谢

Ami*_*iri 122

请记住,使用REST API,这都是您的观点问题.

REST API中的两个关键概念是端点和资源(实体).松散地说,端点要么通过GET返回资源,要么通过POST和PUT等接受资源(或者上面的组合).

可以接受的是,对于POST,您发送的数据可能会也可能不会导致创建新资源及其关联的端点,这很可能不会在POSTed网址下"生存".换句话说,当您发布POST时,您可以将数据发送到某处进行处理.POST端点不是通常可以找到资源的位置.

RFC 2616引用(省略了相关部分,突出显示了相关部分):

9.5 POST

POST方法用于请求源服务器接受请求中包含的实体作为Request-URI中Request-URI标识的资源的新下级.POST旨在允许统一的方法来涵盖以下功能:

  • ...
  • 提供数据块,例如提交表单的结果,数据处理过程;
  • ...

...

POST方法执行的操作可能不会生成可由URI标识的资源.在这种情况下,200(OK)或204(No Content)是适当的响应状态,具体取决于响应是否包括描述结果的实体.

如果已在源服务器上创建资源,则响应应为201(已创建)...

我们已经习惯了代表"事物"或"数据"的端点和资源,无论是用户,消息还是书籍 - 无论问题域是什么.但是,端点也可以公开不同的资源 - 例如搜索结果.

请考虑以下示例:

GET    /books?author=AUTHOR
POST   /books
PUT    /books/ID
DELETE /books/ID
Run Code Online (Sandbox Code Playgroud)

这是典型的REST CRUD.但是,如果我们添加:

POST /books/search

    {
        "keywords": "...",
        "yearRange": {"from": 1945, "to": 2003},
        "genre": "..."
    }
Run Code Online (Sandbox Code Playgroud)

这个端点没有任何非RESTful功能.它以请求体的形式接受数据(实体).该数据是搜索标准 - 与任何其他DTO一样.此端点生成响应请求的资源(实体):搜索结果.搜索结果资源是临时资源,立即提供给客户端,没有重定向,也没有从其他规范网址中公开.

它仍然是REST,除了实体不是书籍 - 请求实体是书籍搜索标准,而响应实体是书籍搜索结果.

  • 201则相反 - 它意味着已创建资源.预计会在某处拥有唯一URI的资源.当`POST`用于CRUD的C部分时,201是合适的.我会选择普通的旧200,可选择204,以获得空的搜索结果. (7认同)

Rob*_*Rob 75

很多人已经接受了这样的做法,即查询字符串太长或太复杂的GET(例如查询字符串不能轻易处理嵌套数据)可以作为POST发送,而复杂/长数据表示在正文中请求.

在HTTP规范中查找POST的规范.这是非常广泛的.(如果你想通过REST中的漏洞驾驶战舰......请使用POST.)

你失去了GET语义的一些好处......就像自动重试一样,因为GET是幂等的,但是如果你能接受它,那么接受使用POST处理真正冗长或复杂的查询可能会更容易.

(lol long exression ...我最近发现,根据HTTP规范,GET 可以包含一个文档正文.有一节说明,"任何请求都可以有一个文档正文,除了本节中列出的文档"......并且它引用的部分没有列出任何.我搜索并找到了一个HTTP作者正在讨论的线程,这是有意的,因此路由器等不必区分不同的消息.但是,练习很多基础设施都可以放弃GET的主体.所以你可以使用体内代表的过滤器来获取,比如POST,但是你要掷骰子.)

  • 有关HTTP GET with body的更多讨论,另请参阅[this](http://stackoverflow.com/questions/978061/http-get-with-request-body)问题. (9认同)

Del*_*lmo 6

简而言之:使用X-HTTP-Method-Override标头进行POST但覆盖HTTP方法.

真实的要求

邮寄/书籍

实体

{"title":"Ipsum","年份":2017}

X-HTTP-Method-Override:GET

在服务器端,检查是否存在标头X-HTTP-Method-Override,然后将其值作为构建到后端中最终端点的路由的方法.另外,将实体主体作为查询字符串.从后端的角度来看,请求只是一个简单的GET.

这样您就可以使设计与REST原则保持一致.

编辑:我知道这个解决方案最初是为了解决某些浏览器和服务器中的PATCH动词问题,但是对于我来说,对于我来说,如果是一个非常长的URL,这就是问题中描述的问题.

  • IETF弃用了X-prefixed HTTP标头:https://tools.ietf.org/html/rfc6648 (2认同)