我正在设计一个(或多或少)在 ASP.NET 和 IIS 上运行的 RESTful 内部 Web 服务。我希望客户端能够在访问大量条目时将查询详细信息传递给服务器,使用 JSON 以已知方式描述查询。问题是发送到服务器的查询会很复杂;它们可能包括聚合、过滤、映射——基本上是LINQ 查询运算符支持的任何内容。这将导致表示查询的 JSON 对象相对较大。
我面临的冲突是,虽然查询GET
在 REST 世界中是语义上的,但在GET
. 我想出了几个选项来解决这个问题。
选项 1:在请求正文中发送查询对象GET
。
GET /namespace/collection/ HTTP/1.1
Content-Length: 22
{ /* query object */ }
显然,这是非标准的,并且某些软件可能会在GET
具有正文的请求上阻塞。(或者更糟糕的是,简单地剥离正文并在没有它的情况下处理请求,这将导致服务器返回不正确的结果集。)
选项 2:使用非标准 HTTP 动词(可能是QUERY
)而不是GET
.
QUERY /namespace/collection/ HTTP/1.1
Content-Length: 22
{ /* query object */ }
虽然这并不完全符合 REST 模式,但它(对我而言)似乎是一个安全的替代方案,因为其他软件(例如任何使用 WebDAV 的软件)似乎使用非标准 HTTP 动词并取得了足够的成功。
选项 3:将查询对象放在非标准 HTTP 标头中。
GET /namespace/collection/ HTTP/1.1
ProjectName-Query: { /* query object */ }
此选项将请求保留为GET
,但需要在 HTTP 标头中填充可能非常大的对象。我了解某些软件对 HTTP 标头设置了任意长度限制,因此如果对象变得太大,这可能会导致问题。
选项 4:使用POST
动词并提供备用端点进行查询。
POST /namespace/collection/query HTTP/1.1
Content-Length: 22
{ /* query object */ }
因为这使用了标准动词而没有标准标题,所以可以保证此方法适用于所有场景。唯一的问题是它偏离了 RESTful 架构,我正在尽我所能保持一致。
这些选项都不是完全正确的。我想知道哪种方式对我正在编写的服务最有意义;它是一个内部 Web 服务(它永远不会向公众公开),但可以通过各种网络安全应用程序(防火墙、内容过滤器等)访问它,我想坚持已知的开发风格、标准和架构尽我所能。