一尘不染

EscapeUriString 和 EscapeDataString 有什么区别?

javascript

如果只处理 url 编码,我应该使用EscapeUriString吗?


阅读 121

收藏
2022-04-14

共1个答案

一尘不染

我没有发现现有的答案令人满意,所以我决定更深入地解决这个问题。令人惊讶的是,答案非常简单:

*(几乎*)没有正当理由使用Uri.EscapeUriString. 如果您需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString. *

* 有关有效用例,请参阅最后一段。

为什么是这样?根据文档

使用 EscapeUriString 方法准备一个未转义的 URI 字符串作为 Uri 构造函数的参数。

这真的没有意义。根据RFC 2396

URI 始终采用“转义”形式,因为转义或取消转义已完成的 URI 可能会改变其语义。

虽然引用的 RFC 已被RFC 3986淘汰,但这一点仍然存在。让我们通过一些具体的例子来验证它:

  1. 您有一个简单的 URI,如下所示:

csharp http://example.org/

Uri.EscapeUriString不会改变它。

  1. 您决定手动编辑查询字符串而不考虑转义:

ruby http://example.org/?key=two words

Uri.EscapeUriString将(正确地)为您逃离空间:

    http://example.org/?key=two%20words
  1. 您决定进一步手动编辑查询字符串:

ruby http://example.org/?parameter=father&son

但是,此字符串不会被 更改Uri.EscapeUriString,因为它假定 & 符号表示另一个键值对的开始。这可能是也可能不是您想要的。

  1. 您决定实际上希望key参数为father&son,因此您通过转义 & 符号手动修复先前的 URL:

perl http://example.org/?parameter=father%26son

但是,Uri.EscapeUriString也会转义百分比字符,导致双重编码:

    http://example.org/?parameter=father%2526son

如您所见,将Uri.EscapeUriString其用于预期目的使得无法将其&用作查询字符串中键或值的一部分,而不是用作多个键值对之间的分隔符。

这是因为,为了使它适合转义完整的 URI,它忽略了保留字符,只转义了既不是保留也不是非保留的字符,顺便说一句,这与文档相反。这样你就不会得到类似的东西http%3A%2F%2Fexample.org%2F,但你最终会遇到上面说明的问题。


最后,如果你的 URI 是有效的,它不需要被转义作为参数传递给 Uri 构造函数,如果它无效,那么调用Uri.EscapeUriString也不是一个神奇的解决方案。实际上,即使不是大多数情况,它也适用于许多情况,但它绝不是可靠的。

您应该始终通过收集键值对和百分比编码来构造您的 URL 和查询字符串,然后将它们与必要的分隔符连接起来。您可以Uri.EscapeDataString用于此目的,但不能使用Uri.EscapeUriString,因为它不会转义保留字符,如上所述。

只有当您无法做到这一点时,例如在处理用户提供的 URI 时,才有意义将其Uri.EscapeUriString用作最后的手段。但是前面提到的警告也适用——如果用户提供的 URI 不明确,结果可能并不理想。

2022-04-14