Rubyで文字列をURLエンコードする方法


135

次のURI::encodeような文字列はどうすればよいですか。

\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>'

私はインターネットについてすべて調べましたが、これを行う方法を見つけていませんでしたが、先日、まったく問題なくこれを実行したことはほぼ確実です。


1
たぶん便利な場合はRuby 1.9の使用:yehudakatz.com/2010/05/05/...
apneadiving

回答:


179
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 CGI.escape str


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

2
force_encoding('binary')もっと自己文書化する選択かもしれません。
muが短すぎる

63
彼らはそのメソッドを廃止しましたCGI.escape。代わりに* *を使用してください。-> http://www.ruby-forum.com/topic/207489#903709URI.www_form_encode* URI.www_form_encode_component* も使用できるはずです が、私はそれらを使用したことがありません
J-Rou

2
require 'open-uri'ここには必要ありません。もしかしてrequire 'uri'
pje 2013

1
@ J-Rou、CGI.escapeはURL全体をエスケープできます。たとえば、クエリパラメータを選択的にエスケープすることはできません。たとえば、'a=&!@&b=&$^'CGI.escapeに渡すと、クエリセパレータですべてをエスケープするため、&値をクエリするためだけに使用できます。addressablegem を使用することをお勧めします。これは、URLをより知的に処理するためのものです。
Alexander.Iljushkin

リモートサーバー上のファイルにアクセスする必要がありました。CGIでのエンコードは機能しませんでしたが、URI.encodeは問題なく機能しました。
Tashows

82

現在では、ERB::Util.url_encodeまたはを使用する必要がありますCGI.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形式仕様は、あなたに与えapplication/x-www-form-urlencodedにエスケープするスペースを必要とする文字列を、+一方、ERB::Util.url_encode次のRFC 3986としてエンコードするためにそれらを必要とし、%20

詳細については、「URI.escapeとCGI.escapeの違いは何ですか?」を参照してください。


70
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のコメントからの引用


11

あなたはそのためにAddressable::URIgemを使うことができます:

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の「application / x-www-form-urlencoded type」を参照してください。+

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" 

このようにすることもできます: CGI.escape('Hello, this is me').gsub("+", "%20") => Hello%2C%20this%20is%20me"宝石を使いたくない場合
Raccoon

5

私は、コードで使用する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'に設定されます。


2

コード:

str = "http://localhost/with spaces and spaces"
encoded = URI::encode(str)
puts encoded

結果:

http://localhost/with%20spaces%20and%20spaces

受信サーバーが古い場合、CGI.escapeにうまく応答しない可能性があります。これはまだ有効な代替手段です。
cesartalves

2

私は元々、完全な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"

URI.escape()が廃止としてマークされている理由と、このREGEXP :: UNSAFE定数はどこにあるのか」の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"

2

手動でさまざまな部分に分割することを考えずに完全なURLを「エンコード」したい場合は、以前使用していた方法と同じ方法で以下が機能することがわかりましたURI.encode

URI.parse(my_url).to_s
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.