如果URL未编码,则稍后会导致问题,因此我
URI.encode(url)
问题是,如果网址已经编码(无论出于何种原因),进一步对网址进行编码,使其无法使用。
除了URI.encode(URI.decode(url))
之外,有没有更好的方法来确保网址只编码一次?
答案 0 :(得分:4)
没有真正的方法,你只需要跟踪字符串是否已经被URI转义。如果你有一个字符串,你不知道它是否已经被URI转义,那就没有好的解决方案了。
通常,您应该在代码中的单个点进行编码。在内存中,通常不应对所有字符串进行URI转义。您应该在从URI解析组件后立即对组件进行unescape。在构造URI时,只在构造完整URI时对它们进行转义/编码。
如果你有一个字符串并且不知道它是否编码,你就不走运了;你需要保持跟踪,理想情况是确保编码发生在明确的系统边界。
答案 1 :(得分:1)
此问题的副本具有用户jordan的部分有效答案
(Ruby - how to encode URL without re-encoding already encoded characters)。
URI.escape
似乎在所有情况下都能以您想要的方式工作,除非 字符已经编码。考虑到这一点,我们可以采取URI.encode
的结果,并使用String#gsub
来"取消编码"只有那些 字符。下面的正则表达式查找
%25
(编码的%
) 通过两个十六进制数字,例如,%252f
返回%2f
:require "uri" DOUBLE_ESCAPED_EXPR = /%25([0-9a-f]{2})/i def escape_uri(uri) URI.encode(uri).gsub(DOUBLE_ESCAPED_EXPR, '%\1') end puts escape_uri("https://www.example.com/url-déjà-vu") # => https://www.example.com/url-d%C3%A9j%C3%A0-vu
它有点笨拙,但它适用于我遇到的所有问题。更好的是,它是幂等的:
URI.encode("http://example.com/#example%example")
# => "http://example.com/%23example%25example"
URI.encode(URI.encode("http://example.com/#example%example"))
# => "http://example.com/%2523example%2525example"
escape_uri("http://example.com/#example%example")
# => "http://example.com/%23example%25example"
escape_uri(escape_uri("http://example.com/#example%example"))
# => "http://example.com/%23example%25example"
答案 2 :(得分:1)
Addressable gem通常具有URI库中缺少的方法。在这种情况下,Addressable :: URI的normalized_encode
方法可以解决这个问题:
weird = "https://www.example.com/this url’s weird"
# => "https://www.example.com/this url’s weird"
encoded = Addressable::URI.normalized_encode weird
# => "https://www.example.com/this%20url%E2%80%99s%20weird"
Addressable::URI.normalized_encode encoded
# => "https://www.example.com/this%20url%E2%80%99s%20weird"
参考文献: http://www.rubydoc.info/gems/addressable/2.3.5/Addressable/URI#normalized_encode-class_method
答案 3 :(得分:0)
我不确定OpenURI中包含哪种方法来执行此操作,因此只需与ternary运算符进行比较。
url == URI.encode(url) ? url : URI.encode(url)
它易读且简单。
if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this
可能还有其他方法,包括检查某些字符的字符串等。但我认为为了保持简单和可读性,这是一个不错的解决方案。
答案 4 :(得分:0)
在编码之前解码URI有什么问题?为了牺牲编码安全性,您牺牲了一些性能:
uri = "www.example.com/%E5%86%99%E7%9C%9F/cats"
URI.encode(uri)
# => www.example.com/%25E5%2586%2599%25E7%259C%259F/cats
URI.encode(URI.decode(uri))
# => www.example.com/%E5%86%99%E7%9C%9F/cats
它的速度比简单编码慢两倍,但比Addressable
之类的替代方法要快许多。