루비에서 문자열을 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#903709 . 당신은 또한 URI.www_form_encode* URI.www_form_encode_component* 를 사용할 수 있어야 하지만, 나는 그것들을 사용한 적이 없습니다
J-Rou

2
require 'open-uri'여기에 필요가 없습니다 . 당신은 의미 했습니까 require 'uri'?
pje

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.escapeCGI / HTML 형식 사양을 따르고 application/x-www-form-urlencoded공백을 이스케이프 처리해야하는 문자열을 제공하는 +반면 RFC 3986을 따르면 ERB::Util.url_encode다음과 같이 인코딩해야합니다 .%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::URI보석을 사용할 수 있습니다 :

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"있는 보석을 사용하지 않으려면
너구리

5

URI 인코딩을 코드에서 더 깨끗하게 사용할 수 있도록 gem을 만들었습니다. 이진 인코딩을 처리합니다.

를 실행 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 인코딩이 실패하면 기본적으로 '이진'인코딩으로 설정됩니다.


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 상수는 어디에 있습니까? "의 두 가지 답변을 기반으로하는 것이을 사용 하는 것 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을 다른 부분으로 수동으로 분할하지 않고 전체 URL을 "인코딩"하려면 다음과 같은 방식으로 작동합니다 URI.encode.

URI.parse(my_url).to_s
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.