在GET期间是否有规范/ RESTful方式将查询详细信息发送到服务器?

Ada*_*ras 5 asp.net iis rest get http

我正在设计一个(或多或少)RESTful内部Web服务,在ASP.NET和IIS上运行.我希望客户端能够在访问大型条目集合时将查询详细信息传递给服务器,使用JSON以已知方式描述查询.问题是发送到服务器的查询会很复杂; 它们可能包括聚合,过滤,映射 - 实质上是LINQ查询运算符支持的任何内容.这将导致表示查询的相对较大的JSON对象.

我面临的冲突是,虽然查询在语义上是GET在REST的世界中,但是没有标准化的方法将大块数据传递给Web服务器GET.我想出了一些解决这个问题的方法.


选项1:GET请求正文中发送查询对象.

GET /namespace/collection/ HTTP/1.1
Content-Length: 22

{ /* query object */ }
Run Code Online (Sandbox Code Playgroud)

显然,这是非标准的,并且某些软件可能会阻塞GET具有正文的请求.(或者更糟糕的是,简单地剥离主体并在没有它的情况下处理请求,这将导致服务器返回不正确的结果集.)


选项2:使用非标准HTTP动词(可能QUERY)而不是GET.

QUERY /namespace/collection/ HTTP/1.1
Content-Length: 22

{ /* query object */ }
Run Code Online (Sandbox Code Playgroud)

虽然这不完全适合REST模式,但似乎(对我而言)是一种安全的替代方案,因为其他软件(例如使用WebDAV的任何软件)似乎使用非标准HTTP动词并取得了足够的成功.


选项3:将查询对象放在非标准HTTP标头中.

GET /namespace/collection/ HTTP/1.1
ProjectName-Query: { /* query object */ }
Run Code Online (Sandbox Code Playgroud)

此选项将请求保持为 GET,但需要填充HTTP头中可能非常大的对象.我理解一些软件对HTTP标头设置任意长度限制,因此如果对象太大,这可能会导致问题.


选项4:使用POST动词并提供备用端点进行查询.

POST /namespace/collection/query HTTP/1.1
Content-Length: 22

{ /* query object */ }
Run Code Online (Sandbox Code Playgroud)

因为它使用标准动词而没有标准标题,所以保证此方法适用于所有场景.唯一的问题是它偏离了RESTful架构,我试图尽可能保持一致.


这些选项都不是正确的.我想知道的是哪种方式对我正在写的服务最有意义; 它是一个内部Web服务(它永远不会暴露给公众),但它可以通过各种网络安全应用程序(防火墙,内容过滤器等)访问,我想坚持已知的开发风格,标准和架构尽我所能.

xwo*_*ker 6

我认为"RESTful查询"有两个资源:QueryQueryResult.

您将查询发布到一个端点(例如"POST/queries /")并使用特定查询的URI(/ queries/123)返回CREATED状态,并使用一个漂亮的RESTful超文本主体告诉您的URL查询结果(例如/ result/123).然后使用GET/result/123访问查询结果.(如果您使用超文本链接回/ queries/123,则奖励积分,以便查询结果的使用者可以检查和修改查询.

详细阐述我想要提出的观点:

如果RESTful基本上被简化为"将业务实体映射到URI"而不是出现明显的问题:"我如何查询我的实体的子集"?解决方案通常是"向'此类型'的所有实体 - URL添加查询字符串" - 为什么它会被称为"查询字符串"?但它开始感觉"错误" - 正如OP中所述 - 如果你想拥有一个完整的查询界面.

原因是,根据此要求,Query将成为一个完整的业务对象本身,不再是资源地址的附录.它不再是次要的,而是主要的.以自己的地址(例如URL)和表示形式成为一种资源变得非常重要.


tec*_*oma 3

我会使用选项 4。很难将大型搜索请求的 json 查询表示形式放入 URL 中,尤其是针对搜索服务器。我同意,在这种情况下它不适合 Restful 风格,因为资源无法通过 URI 来识别。REST 是一个指导方针。如果 REST 无法实现该场景,那么我想做一些事情来解决问题。这里使用 POST 并不安全,但它似乎是正确的解决方案。