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

时间:2013-09-18 20:25:20

标签: asp.net http rest iis get

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

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


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

GET

显然,这是非标准的,某些软件可能会对具有正文的GET /namespace/collection/ HTTP/1.1 Content-Length: 22 { /* query object */ } 请求感到困惑。 (或者更糟糕的是,简单地剥离正文并处理请求而不使用它,这会导致服务器返回不正确的结果集。)


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

GET

虽然这与REST模式不完全相符,但似乎(对我而言)是一种安全的选择,因为其他软件(例如任何使用WebDAV的软件)似乎使用非标准HTTP动词并取得了足够的成功。


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

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

{ /* query object */ }

此选项将请求保留为GET /namespace/collection/ HTTP/1.1 ProjectName-Query: { /* query object */ } ,但需要填充HTTP头中可能非常大的对象。我理解一些软件会在HTTP标头上设置任意长度限制,因此如果对象太大,这可能会导致问题。


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

POST

因为它使用标准动词而没有标准标题,所以此方法可以保证在所有方案中都有效。唯一的问题是它偏离了RESTful架构,我试图尽可能地保持一致。


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

8 个答案:

答案 0 :(得分:6)

我认为“RESTful查询”有两个资源:查询 QueryResult

您将查询发布到一个端点(例如“POST / queries /”)并返回一个CREATED Status,其中包含您特定查询的URI(/ queries / 123)和a nice and RESTful hypertext正文告诉您查询结果的URL(例如/ result / 123)。然后使用GET / result / 123访问查询结果。 (如果您使用超文本链接回/ queries / 123以便查询结果的使用者可以检查和修改查询,则会获得奖励。

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

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

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

我不确定它对你来说看起来多么“规范”,但你可以认真看看OData(开放数据协议):

  

OData是用于创建和使用数据API的标准化协议。   OData建立在像HTTP这样的核心协议上,并且被普遍接受   REST等方法。结果是一种统一的曝光方式   功能齐全的数据API。

即使您没有按原样实施,也有可以重复使用的想法。

具体来说,OData定义batch processing。它用于执行在单个HTTP请求中发送的多个操作。因此,使用OData,您有两种选择:

  1. 对不太长的查询使用GET +查询字符串操作
  2. 使用POST +多部分正文操作来处理更大的事情。
  3. 有关OData上下文中最大uri长度的更多信息:OData Url Length Limitations

    此外,许多安全设备(路由器,防火墙等)根本不会让您的选项1,2和3通过。 GET + Body是不寻常的,GET +一个大的表单值可能会被杀死,而自定义HTTP动词也很不寻常。

    总的来说,我认为POST +正文似乎是最好的选择(无论是严格的多部分 - 比如在OData中 - 或者不是由你决定)

答案 3 :(得分:1)

在仔细考虑了这个之后,我将给出另一个答案。

当您声明JSON表示将“相对较大”时,您在估计的字符数中是什么意思? IE可以处理超过2,000个字符的URL。查询会变得更大吗?因为我认为查询字符串是要走的路。现在我正在使用一个使用JSONP的系统,所以除了在查询字符串中将所有数据作为JSON包传递之外别无选择,它工作正常。使用GET动词不仅在语义上是正确的,而且还包括能够将URL添加到结果的功能。用户可以通过您在内部使用的电子邮件或其他电子通信系统轻松共享数据结果的链接。

答案 4 :(得分:1)

我不确定这是否有帮助,但即使对于所有Quickbooks API,返回大型结果集(如Read All)的查询,或返回大型JSON结果集的LINQ扩展程序查询,我们都使用GET与相关内容类型和编码(如ASCII) 。该请求使用compressionFormat作为None,响应使用GZIP compressionFormat。 https://developer.intuit.com/apiexplorer?apiName=V3QBO

答案 5 :(得分:1)

最好的方法是序列化搜索JSON对象并将其作为查询参数传递。您确定现代浏览器和服务器的时间太长了吗?现代浏览器和服务器可以处理相当大的GET查询参数长度,数千个字符。

如果对象的大小将超过8k字符,则可能是X-Custom-Query-Parameters-JSON之类的扩展标头。

在您的特定情况下,序列化JSON对象将包含多少个字符?

有关字符限制的一些相关问题

What is the limit on QueryString / GET / URL parameters

Is there a practical HTTP Header length limit?

答案 6 :(得分:0)

一个有趣的问题。我没有关于你想要做什么的具体细节,但我想知道用一种资源优雅地处理它是否太多了。您可能希望根据请求的主要特征将其分解为几种不同的类型。如果您只是试图通过HTTP请求公开应该是SQL查询的内容,那么我认为没有任何方法可以在没有混乱的情况下实现它。只需在查询字符串中传递SQL查询,然后停止尝试找到正确的方法 - 它就不存在了。

答案 7 :(得分:0)

使用POST,并将查询/参数作为键值对传递给正文中的json。在asp.net代码中,将有效负载转换为字典对象也变得更加容易。

Dictionary<string,object>