首页 文章

Ruby url编码字符串

提问于
浏览
113

我如何URI ::编码一个字符串,如:

\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a

要获得以下格式:

%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A

(根据RFC 1738)

这是我尝试过的:

irb(main):123:0> URI::encode "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a"
ArgumentError: invalid byte sequence in UTF-8
    from /usr/local/lib/ruby/1.9.1/uri/common.rb:219:in `gsub'
    from /usr/local/lib/ruby/1.9.1/uri/common.rb:219:in `escape'
    from /usr/local/lib/ruby/1.9.1/uri/common.rb:505:in `escape'
    from (irb):123
    from /usr/local/bin/irb:12:in `<main>'

也,

irb(main):126:0> CGI::escape "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a"
ArgumentError: invalid byte sequence in UTF-8
    from /usr/local/lib/ruby/1.9.1/cgi/util.rb:7:in `gsub'
    from /usr/local/lib/ruby/1.9.1/cgi/util.rb:7:in `escape'
    from (irb):126
    from /usr/local/bin/irb:12:in `<main>'

我看了很多关于互联网的事情并没有找到(或者更可能错过)一种方法来做到这一点,虽然我几乎肯定我前几天毫无困难地做了这件事 .

谢谢!

6 回答

  • 60
    require 'uri'
    str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a".force_encoding('ASCII-8BIT')
    puts URI::encode(str)
    

    更新:请参阅下面的评论Ruby url encoding string

  • 2
    str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a"
    require 'cgi'
    CGI.escape(str)
    # => "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A"
    

    取自@ J-Rou的评论

  • 5

    如今,你应该使用 ERB::Util.url_encodeCGI.escape . 它们之间的主要区别在于它们对空间的处理:

    >> ERB::Util.url_encode("foo/bar? baz&")
    => "foo%2Fbar%3F%20baz%26"
    
    >> CGI.escape("foo/bar? baz&")
    => "foo%2Fbar%3F+baz%26"
    

    CGI.escape 跟在CGI/HTML forms spec之后,给你一个 application/x-www-form-urlencoded 字符串,它需要空格转义为 + ,而 ERB::Util.url_encode 跟随RFC 3986,这要求它们被编码为 %20 .

    有关更多讨论,请参阅this answer .

  • 7

    您可以使用 Addressable::URI gem:

    require 'addressable/uri'   
    string = '\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a'
    Addressable::URI.encode_component(string, Addressable::URI::CharacterClasses::QUERY)
    # "%5Cx12%5Cx34%5Cx56%5Cx78%5Cx9a%5Cxbc%5Cxde%5Cxf1%5Cx23%5Cx45%5Cx67%5Cx89%5Cxab%5Cxcd%5Cxef%5Cx12%5Cx34%5Cx56%5Cx78%5Cx9a"
    

    它使用比 CGI.escape 更现代的格式,例如,它正确地将空间编码为 %20 而不是 + 符号,您可以在wikipedia article中阅读更多内容

    2.1.2 :008 > CGI.escape('Hello, this is me')
     => "Hello%2C+this+is+me" 
    2.1.2 :009 > Addressable::URI.encode_component('Hello, this is me', Addressable::URI::CharacterClasses::QUERY)
     => "Hello,%20this%20is%20me"
    
  • 160

    我创建了一个gem来使uri编码更清晰,以便在代码中使用 . 它为您处理二进制编码(在上面的代码中添加了一些示例内容) .

    运行 gem install uri-handler .

    require 'uri-handler'
    
    str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a".to_uri
    # => "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A"
    

    它将uri转换功能添加到String类中 . 您也可以使用您想要使用的可选编码字符串传递一个参数(默认情况下,如果直接UTF-8编码失败,则设置为编码'binary') .

  • 66

    我原本试图从完整的url字符串中仅在文件名(不在路径上)上转义特殊字符 . ERB::Util.url_encode 无法使用 .

    helper.send(:url_encode, "http://example.com/?a=\11\15")
    # => "http%3A%2F%2Fexample.com%2F%3Fa%3D%09%0D"
    

    基于不同SO question的2个答案,看起来 URI::RFC2396_Parser#escape 比使用 URI::Escape#escape 更好 . 但是,它们对我来说都表现得一样 .

    URI.escape("http://example.com/?a=\11\15")
    # => "http://example.com/?a=%09%0D"
    URI::Parser.new.escape("http://example.com/?a=\11\15")
    # => "http://example.com/?a=%09%0D"
    

相关问题