Sự khác biệt giữa những gì URI.escape
và CGI.escape
và cái nào tôi nên sử dụng?
Sự khác biệt giữa những gì URI.escape
và CGI.escape
và cái nào tôi nên sử dụng?
Câu trả lời:
Có một số khác biệt nhỏ, nhưng điểm quan trọng là URI.escape
đã bị phản đối trong Ruby 1.9.2 ... vì vậy hãy sử dụng CGI::escape
hoặc ERB :: Util.url_encode .
Có một cuộc thảo luận dài về ruby-core dành cho những người quan tâm cũng đề cập đến WEBrick :: HTTPUtils.escape và WEBrick :: HTTPUtils.escape_form .
ERB::Util.url_encode
đúng cách %20
cho các không gian
Sự khác biệt giữa rìu và kiếm và tôi nên sử dụng loại nào? Vâng, nó phụ thuộc vào những gì bạn cần làm.
URI.escape
được cho là mã hóa một chuỗi (URL) thành cái gọi là " Mã hóa phần trăm ".
CGI::escape
đến từ thông số CGI , mô tả cách dữ liệu nên được mã hóa / giải mã giữa máy chủ web và ứng dụng.
Bây giờ, hãy nói rằng bạn cần thoát URI trong ứng dụng của mình. Đây là một trường hợp sử dụng cụ thể hơn. Cho rằng, cộng đồng Ruby đã sử dụng URI.escape
trong nhiều năm. Vấn đề với URI.escape
là nó không thể xử lý thông số 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
được đánh dấu là lỗi thời:
Hơn nữa, URI.encode hiện tại là gsub đơn giản. Nhưng tôi nghĩ nó nên tách một URI thành các thành phần, sau đó thoát từng thành phần và cuối cùng tham gia chúng.
Vì vậy, URI.encode hiện tại được coi là có hại và không dùng nữa. Điều này sẽ được loại bỏ hoặc thay đổi hành vi quyết liệt.
Sự thay thế tại thời điểm này là gì?
Như tôi đã nói ở trên, URI.encode hiện tại sai ở cấp độ spec. Vì vậy, chúng tôi sẽ không cung cấp sự thay thế chính xác. Sự thay thế sẽ thay đổi tùy theo trường hợp sử dụng của nó.
Thật không may, không có một từ nào về nó trong các tài liệu, cách duy nhất để biết về nó là kiểm tra nguồn hoặc chạy tập lệnh với các cảnh báo ở cấp độ dài (-wW2
) (hoặc sử dụng một số google-fu).
Một số đề xuất sử dụng CGI::Escape
cho các tham số truy vấn, vì bạn không thể thoát toàn bộ URI:
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
chỉ nên được sử dụng cho các tham số truy vấn, nhưng kết quả sẽ lại, so với thông số kỹ thuật. Trên thực tế, trường hợp sử dụng phổ biến nhất là thoát dữ liệu biểu mẫu, chẳng hạn như trong khi gửi mộtapplication/x-www-form-urlencoded
yêu cầu POST.
Cũng được đề cập WEBrick::HTTPUtils.escape
là không có nhiều cải tiến (một lần nữa, nó chỉ là một đơn giản gsub
, đó là IMO, thậm chí là một lựa chọn tồi tệ hơn 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"
Gần nhất với thông số kỹ thuật dường như là viên ngọc Địa chỉ :
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"
Lưu ý rằng, không giống như tất cả các tùy chọn trước đó, Địa chỉ không thoát #
, và đây là hành vi dự kiến. bạn muốn giữ #
hàm băm trong đường dẫn URI nhưng không phải trong truy vấn URI.
Vấn đề duy nhất còn lại là chúng tôi đã không thoát khỏi các tham số truy vấn của mình một cách chính xác, điều này đưa chúng ta đến kết luận: chúng ta không nên sử dụng một phương thức duy nhất cho toàn bộ URI, vì cho đến nay vẫn chưa có giải pháp hoàn hảo. Như bạn thấy &
đã không thoát khỏi "Blog của tôi và Blog của bạn". Chúng tôi cần sử dụng một hình thức thoát khác nhau cho các tham số truy vấn, nơi người dùng có thể đặt các ký tự khác nhau có ý nghĩa đặc biệt trong URL. Nhập mã hóa URL. Mã hóa URL nên được sử dụng cho mọi giá trị truy vấn "đáng ngờ", tương tự như những gì ERB::Util.url_encode
:
ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""
Thật tuyệt nhưng chúng tôi đã yêu cầu Địa chỉ:
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"
Phần kết luận:
URI.escape
hoặc tương tựCGI::escape
nếu bạn chỉ cần thoát mẫuAddressable
là một trong những viên ngọc của mình, trước tiên bạn có thể phân tích URL, fi rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Addressable:URL
, sau đó bạn có thể gọi tất cả các phương thức cá thể trên đó, có thể một trong số chúng sẽ mang lại cho bạn kết quả mong muốn: rubydoc.info/gems/addressable/Addressable/URI
URI.escape lấy tham số thứ hai cho phép bạn đánh dấu những gì không an toàn. Xem APIDock:
CGI::escape
là tốt để thoát khỏi đoạn văn bản để chúng có thể được sử dụng trong các tham số truy vấn url (chuỗi sau '?'). Ví dụ: nếu bạn muốn có tham số chứa các ký tự gạch chéo trong url, bạn CGI :: thoát chuỗi đó trước rồi chèn nó vào url.
Tuy nhiên, trong Rails có lẽ bạn sẽ không được sử dụng trực tiếp. Thông thường bạn sử dụng hash.to_param
, sẽ sử dụng CGI::escape
dưới mui xe.
URI::escape
là tốt để thoát một url không được thoát đúng. Ví dụ: một số trang web xuất url sai / không thoát trong thẻ neo của họ. Nếu chương trình của bạn sử dụng các url này để lấy thêm tài nguyên, OpenURI sẽ phàn nàn rằng các url không hợp lệ. Bạn cần URI::escape
những thứ này để biến nó thành một url hợp lệ. Vì vậy, nó được sử dụng để thoát khỏi toàn bộ chuỗi URI để làm cho nó phù hợp. Theo từ của tôi, URI :: unescape làm cho một url có thể đọc được bởi con người và URI :: esc làm cho nó hợp lệ với các trình duyệt.
Đây là thuật ngữ giáo dân của tôi và cảm thấy thoải mái để sửa những điều đó.
Sự khác biệt là URI.escape không hoạt động ...
CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"
URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
CGI.escape là để thoát một giá trị URL trong chuỗi truy vấn. Tất cả các ký tự không rơi vào ALPHA, DIGIT, '_', '-', '.' và bộ ký tự '' được thoát.
Nhưng điều đó sẽ làm cho một URL không chính xác, vì một url cần phải có '/', ':', '?', '[', '&', '=' Và ';'. Có lẽ nhiều hơn tôi không thể nghĩ ra khỏi đỉnh đầu của tôi.
URI.escape để các ký tự URL đó một mình và cố gắng tìm các khóa và giá trị chuỗi truy vấn để thoát. Tuy nhiên, điều này thực sự không thể phụ thuộc vào vì các giá trị có thể có tất cả các loại ký tự ngăn lối thoát dễ dàng. Về cơ bản, đã quá muộn. Nhưng nếu URL có thể phụ thuộc vào đơn giản (không có '&' và '=' v.v. trong các giá trị), thì hàm này có thể được sử dụng để thoát các ký tự có thể không đọc được hoặc không hợp lệ.
Nói chung - luôn luôn sử dụng CGI.escape trên các khóa và giá trị riêng lẻ trước khi nối chúng với '&' và thêm chúng sau '?'.
CGI.escape không hoạt động với API OpenProject. Nó mã hóa [] ,: chứ không phải +. Tôi đã hack cái này với nhau dường như hoạt động cho API của OpenProject. Nhưng tôi chắc chắn rằng nó thiếu một số .subub. Nó có thể gần như tồi tệ như URI.escape, nhưng nó sẽ không cung cấp cho bạn các lỗi lỗi thời.
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\"]")
Cả hai đầu ra:
=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart% 22] "