URI.escape와 CGI.escape의 차이점은 무엇입니까?


147

차이 무엇 URI.escapeCGI.escape어느 하나를 사용해야합니까는?

답변:


124

이 몇 가지 작은 차이가 있었지만, 중요한 점은이있다 URI.escape되었습니다 되지 그렇게 사용 ... 루비 1.9.2에서 CGI::escape또는 ERB :: Util.url_encode .

WEBrick :: HTTPUtils.escapeWEBrick :: HTTPUtils.escape_form을 언급하는 관심있는 사람들을 위해 루비 코어에 대한 긴 토론 이 있습니다 .


11
난 그냥에 대한 코멘트 보았다 - 그냥 혼란에 추가 할 stackoverflow.com/questions/4967608/...을 누군가가 공간 대신 20 %의 CGI 탈출 용도를 '+'언급 한 곳, 그리고 그것은 '스펙'...에 있다는
루이 세이 어스

18
대안은 공간에 ERB::Util.url_encode적절하게 사용 %20 하는 것입니다
riffraff

1
@Ernest : 참조 : github.com/ruby/ruby/commit/... (대답은 업데이트)
마크 - 앙드레 Lafortune

4
ruby-doc.org/stdlib-2.0.0/libdoc/uri/rdoc/URI/Escape.html . 루비 2.0.0에는 URI.escape 모듈이 있습니다. 더 이상 사용되지 않는 이유는 무엇입니까?
user938363

1
@ user938363 거기에서 쇼 소스를 클릭하면 여전히 더 이상 사용되지 않는 것으로 표시됩니다.
drewish

229

도끼와 칼의 차이점은 무엇이며 어떤 칼을 사용해야합니까? 글쎄, 그것은 당신이해야 할 일에 달려 있습니다.

URI.escape문자열 (URL)을 소위 " 백분율 인코딩 " 으로 인코딩해야했습니다 .

CGI::escape웹 서버와 응용 프로그램간에 데이터를 인코딩 / 디코딩하는 방법을 설명하는 CGI 사양 에서 나옵니다 .

이제 앱에서 URI를 이스케이프해야한다고 가정 해 봅시다. 보다 구체적인 사용 사례입니다. 이를 위해 Ruby 커뮤니티 URI.escape는 수년간 사용 되었습니다. 문제 URI.escape는 RFC-3896 스펙을 처리 할 수 ​​없다는 것입니다.

URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog"

URI.escape 사용되지 않는 것으로 표시되었습니다.

또한 현재 URI.encode는 간단한 gsub입니다. 그러나 URI를 구성 요소로 분할 한 다음 각 구성 요소를 이스케이프 처리하고 마지막으로 결합해야한다고 생각합니다.

따라서 현재 URI.encode는 유해하고 사용되지 않는 것으로 간주됩니다. 이것은 제거되거나 동작이 크게 변경됩니다.

현재 대체품은 무엇입니까?

위에서 말했듯이 현재 URI.encode는 사양 수준에서 잘못되었습니다. 따라서 정확한 교체를 제공하지 않습니다. 교체는 사용 사례에 따라 다릅니다.

https://bugs.ruby-lang.org/issues/4167

불행히도 문서에는 한 마디도 없습니다. 알 수있는 유일한 방법은 소스를 확인하거나 자세한 수준 ( -wW2) 으로 경고와 함께 스크립트를 실행 하거나 일부 google-fu를 사용하는 것입니다.

일부 는 전체 URI를 이스케이프 할 수 없으므로 쿼리 매개 변수 에 사용하도록 제안 했습니다 CGI::Escape.

CGI::escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http%3A%2F%2Fgoogle.com%2Ffoo%3Fbar%3Dat%23anchor%26title%3DMy+Blog+%26+Your+Blog"

CGI::escape쿼리 매개 변수에만 사용해야하지만 결과는 스펙에 반합니다. 실제로 가장 일반적인 사용 사례는 application/x-www-form-urlencodedPOST 요청 을 보내는 동안과 같은 양식 데이터를 이스케이프 처리하는 것입니다.

또한 WEBrick::HTTPUtils.escape많은 개선 사항이 언급 되지 않았습니다 (다시 단순한 것 gsub, 즉 IMO, 심지어 더 나쁜 옵션입니다 URI.escape).

WEBrick::HTTPUtils.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog" 

스펙에 가장 가까운 것은 Addressable gem 인 것 같습니다 .

require 'addressable/uri'
Addressable::URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at#anchor&title=My%20Blog%20&%20Your%20Blog"

이전의 모든 옵션과 달리 Addressable은 이스케이프되지 않으며 #이는 예상되는 동작입니다. #URI 쿼리 에는 해시 를 유지하고 URI 경로 에는 해시 를 유지하려고 합니다.

남은 유일한 문제는 쿼리 매개 변수를 올바르게 이스케이프하지 않았다는 것입니다. 결론은 완벽한 솔루션이 없기 때문에 전체 URI에 단일 메서드를 사용해서는 안됩니다. 보시다시피 &"내 블로그 및 블로그"에서 이스케이프되지 않았습니다. 사용자는 URL에서 특별한 의미를 가진 다른 문자를 넣을 수있는 쿼리 매개 변수에 대해 다른 형식의 이스케이프를 사용해야합니다. URL 인코딩을 입력하십시오. 다음과 비슷한 "의심스러운"쿼리 값마다 URL 인코딩을 사용해야합니다 ERB::Util.url_encode.

ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""

멋지지만 이미 주소 지정이 필요했습니다.

uri = Addressable::URI.parse("http://www.go.com/foo")
# => #<Addressable::URI:0x186feb0 URI:http://www.go.com/foo>
uri.query_values = {title: "My Blog & Your Blog"}
uri.normalize.to_s
# => "http://www.go.com/foo?title=My%20Blog%20%26%20Your%20Blog"

결론:

  • 사용하지 마십시오 URI.escape또는 이와 유사한
  • CGI::escape양식 이스케이프 만 필요한 경우 사용
  • URI로 작업해야하는 경우 주소 지정 가능을 사용하십시오. URL 인코딩, 양식 인코딩을 제공하고 URL을 정규화합니다.
  • Rails 프로젝트 인 경우 " Rails에서 문자열을 어떻게 이스케이프합니까? "를 확인하십시오.

정보 주셔서 감사합니다. 괭이 테스트 경고가 사라졌습니다. 아래에 갈퀴와 괭이가 있습니다.
Douglas G. Allen

@Ernest에 대한 훌륭한 설명이지만, 이것의 문제점은 내가 만들려고하지 않고 제어 할 수없는 외부 URL에서는 작동하지 않는다는 것입니다. 예를 들어 웹 페이지에서 URL을 읽은 다음 해당 URL에 액세스하려고 시도하는 크롤러 (액세스 전에 인코딩해야 함).
amit_saxena

@amit_saxena 만약 당신 Addressable이 당신의 보석 중 하나로 가질 여유가 있다면 , 먼저 URL을 분석 할 수 있습니다. fi rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Ernest

흥미 롭습니다! 그러나 다시, 나는 이것을 사용하여 원래 URL에서 매개 변수의 해시를 얻을 수 없으므로 설명대로 인코딩합니다. 내 경우의 흐름은 다음과 같습니다. 피드에서 외부 URL을 가져옵니다-> 그런 다음 인코딩해야합니다-> http 클라이언트로 전달하여 콘텐츠를 가져옵니다. 이제 외부 URL을 올바르게 인코딩하지 않으면 루비 기반 HTTP 클라이언트가 잘못된 URI 오류로 실패합니다.
amit_saxena 2018

@amit_saxena 구문 분석 메소드는의 인스턴스를 반환합니다. Addressable:URL그러면 모든 인스턴스 메소드를 호출 할 수 있으며, 그 중 하나가 원하는 결과를 얻을 수 있습니다. rubydoc.info/gems/addressable/Addressable/URI
Ernest


6

CGI::escape텍스트 세그먼트를 이스케이프 처리하여 URL 쿼리 매개 변수 ( '?'뒤의 문자열)에 사용할 수 있습니다. 예를 들어 URL에 슬래시 문자가 포함 된 매개 변수를 사용하려면 해당 문자열을 먼저 CGI :: escape 한 다음 URL에 삽입하십시오.

그러나 Rails에서는 아마 직접 사용하지 않을 것입니다. 일반적으로 후드를 hash.to_param사용하는을 사용 CGI::escape합니다.


URI::escape제대로 이스케이프되지 않은 URL을 이스케이프 처리하는 데 좋습니다. 예를 들어 일부 웹 사이트는 앵커 태그에 잘못 / 이스케이프되지 않은 URL을 출력합니다. 프로그램이 이러한 URL을 사용하여 더 많은 리소스를 가져 오는 경우 OpenURI는 URL이 유효하지 않다고 불평합니다. URI::escape유효한 URL로 만들 려면 이것들이 필요합니다 . 따라서 전체 URI 문자열을 이스케이프 처리하여 적절하게 사용하는 데 사용됩니다. 내 말로 URI :: unescape는 URL을 사람이 읽을 수있게 만들고 URI :: escape는 브라우저에 유효하게 만듭니다.

이것들은 나의 평신도의 용어이며 자유롭게 고칠 수 있습니다.


1

차이점은 URI.escape가 작동하지 않는다는 것입니다.

CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"

URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"

2
잘못된 테스트 사례를 선택했습니다. / 's,?'s 및 = 's는 모두 유효한 URI의 일부이므로 이스케이프되지 않습니다. 특히 쿼리 문자열에서 이스케이프해야하는 다른 문자는 있어야합니다.
Gerard ONeill

@ GerardONeill URI.escape가 작동하지 않고 신뢰할 수없는 방법을 보여주기 위해 테스트 사례를 정확하게 선택했습니다. URI.escape가 쿼리 문자열 만 이스케이프 처리하고 있다고 제안하고 있습니까? &를 인코딩하려면 매개 변수 값이 언제 완료되는지 어떻게 알 수 있습니까? 어쩌면 그것이 쓸모없는 이유일까요?
Radu Simionescu

1
정확히 무슨 말인지. URI 이스케이프는 URL을 구문 분석하고 개별 매개 변수라고 생각하는 것을 분리하고 이스케이프 한 후 다시 묶어야합니다. 그것조차 지저분 할 수 있습니다. 그러나 그렇게하지는 않습니다-나머지 문자를 이스케이프 처리하는 동안 일부 문자를 이스케이프 처리하지 않으므로 불완전합니다. 특히 매개 변수가 혼란스럽지 않다는 것을 알고있는 경우 간단한 경우에 사용할 수 있습니다.
Gerard ONeill

0

CGI.escape는 쿼리 문자열에서 URL 값을 이스케이프하기위한 것입니다. ALPHA, DIGIT, '_', '-', '.'에 속하지 않는 모든 문자 ''문자 세트가 이스케이프됩니다.

그러나 URL에 '/', ':', '?', '[', '&', '='및 ';'이 필요하기 때문에 URL이 올바르지 않습니다. 아마도 나는 내 머리 꼭대기에서 생각할 수없는 것입니다.

URI.escape는 해당 URL 문자 만 남겨두고 이스케이프 할 쿼리 문자열 키와 값을 찾습니다. 그러나 값은 모든 종류의 문자를 가질 수 있으므로 쉽게 벗어날 수 없으므로 실제로 의존 할 수 없습니다. 기본적으로 너무 늦었습니다. 그러나 URL을 단순하게 사용할 수 있으면 (값에 '&'및 '='등 없음)이 함수를 사용하여 읽을 수 없거나 잘못된 문자를 이스케이프 할 수 있습니다.

일반적으로 항상 '&'로 결합하고 '?'뒤에 추가하기 전에 개별 키와 값에 CGI.escape를 사용하십시오.


0

CGI.escape는 OpenProject API에서 작동하지 않았습니다. +가 아닌 []를 인코딩했습니다. 나는 OpenProject의 API에서 지금까지 작동하는 것처럼 이것을 해킹했습니다. 그러나 일부 .gsub가 누락되었다고 확신합니다. URI.escape만큼 나쁘지만 사용되지 않는 오류는 발생하지 않습니다.

class XXX
      def self.encode(path)
        path, query = path.split("?", 2)
        return path if query.nil?
        query = CGI.escape(query).gsub("%3A", ":").gsub("%3D","=").gsub("%5B","[").gsub("%5D","]").gsub("%2C",",").gsub("+","%20")
        return [path,query].join("?")
      end
end

XXX.encode("http://test.com/some/path?query=[box: \"cart\"]")
URI.encode("http://test.com/some/path?query=[box: \"cart\"]")

두 가지 출력 :

=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart % 22] "

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