我有一些我正在编写的 Web 服务,并且我正在尝试尽可能地 RESTful。我使用在 IIS/ASP.NET/SharePoint 内运行的 HTTPHandler 托管这些 Web 服务。
我的大多数服务都需要 HTTP GET。我有两个只是返回一些数据(即查询)并且将是Idempotent,但参数可能有些复杂。它们都可以在服务的参数中包含至少在 URL 的 PATH 部分中不允许使用的字符。
使用 IIS、ASP.NET 和 SharePoint,我发现 URL 路径中的以下字符甚至无法到达我的 HttpHandler,即使 Url 编码(请求爆炸了,我对此没有任何简单的控制) :
- % (%25)
- & (%26)
- * (%2a, 但没有 Url 编码)
- + (%2b)
- : (%3a)
- < (%3c)
(%3e)
以下字符进入了我的 HttpHandler,但即使 Url 编码,UriTemplate 也无法正确处理它们:
(%23)
- . (%2e,但没有 Url 编码;UriTemplate 删除了“。”如果是 / 之前的最后一个字符)
- ? (%3f)
- /(%2f - UriTemplate 因明显原因而失败,即使 UrlEncoded 也是如此)
- \ (%5c)
所以,我已经有些彻底,但我需要在查询字符串中测试这些 url 编码的字符。看来这将在那里大部分工作。
在我的一项服务中,作为参数的特殊字符在语义上是查询/过滤器的一部分(实际上是搜索服务的搜索词),但在另一项服务中,它们并不是查询/过滤器的一部分,因此理想情况下它们是路径而不是查询字符串。
我的问题是,什么选择是最好的?以下是我知道的一些:
使用 HTTP GET 和查询字符串。 任何可能使用特殊字符的内容都应该在查询字符串上并进行 Url 编码。 这是我倾向于的地方,但我担心查询字符串过长(IE 有 2083 个限制)
在路径中使用 HTTP GET 和 base64 编码。 对于可能使用特殊字符的任何参数,请使用修改后的 Base64 作为 URL,并在首选时将它们保留为路径的一部分。 我试过这个并且它有效,但它有点难看。仍然担心极长的查询字符串。
使用 HTTP POST 和消息正文。 任何可能使用特殊字符的内容都应该在请求的正文中。 似乎是一个不错的解决方案,但是帖子被理解为不是幂等的,并且(我认为)通常是为了更改(而这里没有发生更改)。
使用 HTTP GET 和消息正文。 任何可能使用特殊字符的内容都应该在请求的正文中。根据SO:HTTP GET with request body和Roy Fielding这似乎是个坏主意。
根据请求的大小,使用 #3 和上面的 #1 或 #2 的组合。
其他???
请注意,在某些情况下,我可能能够改变一些东西以防止特殊字符(我可能会这样做),但我无法在所有情况下都这样做。
关于 URI 长度,RFC2616 Sec3.2.1说明如下:
HTTP 协议对 URI 的长度没有任何先验限制。服务器必须能够处理它们所服务的任何资源的 URI,并且如果它们提供可以生成此类 URI 的基于 GET 的表单,则应该能够处理无限长度的 URI。如果 URI 比服务器可以处理的长(参见第 10.4.15 节),服务器应该返回 414(Request-URI Too Long)状态。
Note: Servers ought to be cautious about depending on URI lengths
above 255 bytes, because some older client or proxy
implementations might not properly support these lengths.
此外,Internet Explorer 中的最大 URL 长度为 2,083 个字符。