Jaka jest różnica między URI.escapei, CGI.escapea którego należy użyć?
Jaka jest różnica między URI.escapei, CGI.escapea którego należy użyć?
Odpowiedzi:
Były pewne drobne różnice, ale ważne jest to, że URI.escapezostała zaniechana w Ruby 1.9.2 ... więc używać CGI::escapelub ERB :: Util.url_encode .
Dla zainteresowanych istnieje długa dyskusja na temat ruby-core, w której wspomina się również o WEBrick :: HTTPUtils.escape i WEBrick :: HTTPUtils.escape_form .
ERB::Util.url_encodetego, co właściwie używa %20 do spacji
Jaka jest różnica między toporem a mieczem i którego powinienem użyć? To zależy od tego, co musisz zrobić.
URI.escapemiał zakodować ciąg znaków (URL) w tzw. „ kodowaniu procentowym ”.
CGI::escapepochodzi ze specyfikacji CGI , która opisuje sposób kodowania / dekodowania danych między serwerem WWW a aplikacją.
Teraz załóżmy, że musisz uciec przed identyfikatorem URI w swojej aplikacji. Jest to bardziej szczegółowy przypadek użycia. W tym celu społeczność Ruby używana URI.escapeprzez lata. Problem URI.escapepolegał na tym, że nie mógł obsłużyć specyfikacji 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 został oznaczony jako przestarzały:
Ponadto obecny kod URI.encode jest prosty gsub. Ale myślę, że powinno podzielić URI na komponenty, następnie uciec przed każdym komponentem i ostatecznie połączyć je.
Dlatego obecny kod URI.encode jest uważany za szkodliwy i przestarzały. Zostanie to usunięte lub drastycznie zmieni zachowanie.
Jaki jest w tej chwili zamiennik?
Jak powiedziałem powyżej, obecny kod URI.encode jest nieprawidłowy na poziomie specyfikacji. Dlatego nie zapewnimy dokładnej wymiany. Wymiana będzie się różnić w zależności od przypadku użycia.
Niestety w dokumentach nie ma ani słowa na ten temat, jedynym sposobem, aby się o tym dowiedzieć, jest sprawdzenie źródła lub uruchomienie skryptu z ostrzeżeniami na poziomie szczegółowym ( -wW2) (lub użycie jakiegoś google-fu).
Niektórzy proponowali użycie CGI::Escapejako parametrów zapytania, ponieważ nie można było uciec przed całym identyfikatorem 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::escapepowinien być używany tylko dla parametrów zapytania, ale wyniki będą ponownie niezgodne ze specyfikacją. W rzeczywistości najczęstszym przypadkiem użycia jest ucieczka przed danymi z formularza, na przykład podczas wysyłania application/x-www-form-urlencodedżądania POST.
Wspomniano również o WEBrick::HTTPUtils.escapeniewielkiej poprawie (znowu to po prostu prosta gsub, czyli IMO, nawet gorsza opcja niż 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"
Najbardziej zbliżony do specyfikacji wydaje się klejnot adresowalny :
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"
Zwróć uwagę, że w przeciwieństwie do wszystkich poprzednich opcji, Adresowalne nie zmienia znaczenia #i jest to oczekiwane zachowanie. chcesz zachować #skrót w ścieżce URI, ale nie w zapytaniu URI.
Jedynym problemem, jaki pozostał, jest to, że nie pominęliśmy poprawnie naszych parametrów zapytania, co prowadzi nas do wniosku: nie powinniśmy używać jednej metody dla całego identyfikatora URI, ponieważ nie ma (jak dotąd) idealnego rozwiązania. Jak widzisz, &nie został zmieniony z „Mój blog i Twój blog”. Musimy użyć innej formy ucieczki dla parametrów zapytania, gdzie użytkownicy mogą umieszczać różne znaki o specjalnym znaczeniu w adresach URL. Wpisz kodowanie adresu URL. Kodowanie adresu URL powinno być używane dla każdej „podejrzanej” wartości zapytania, podobnie jak w przypadku ERB::Util.url_encode:
ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""
To fajne, ale już wymagaliśmy Adresowalny:
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"
Wniosek:
URI.escapeani podobnychCGI::escapejeśli potrzebujesz tylko ucieczki z formyAddressablejednego ze swoich klejnotów, możesz najpierw przeanalizować adres URL, fi rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Addressable:URL, możesz wtedy wywołać wszystkie metody instancji na niej, może jedna z nich przyniesie pożądane rezultaty: rubydoc.info/gems/addressable/Addressable/URI
URI.escape przyjmuje drugi parametr, który pozwala oznaczyć, co jest niebezpieczne. Zobacz APIDock:
CGI::escapejest dobry do zmiany znaczenia segmentów tekstu, aby można ich było używać w parametrach zapytania URL (ciągi znaków po znaku „?”). Na przykład, jeśli chcesz, aby parametr zawierał znaki ukośnika w adresie URL, najpierw CGI :: zmieniamy znaczenie tego ciągu, a następnie wstawiamy go do adresu URL.
Jednak w Railsach prawdopodobnie nie będziesz go używać bezpośrednio. Zwykle używasz tego hash.to_param, który będzie używany CGI::escapepod maską.
URI::escapejest dobry do ucieczki przed adresem URL, który nie został poprawnie zmieniony. Na przykład niektóre witryny wyświetlają nieprawidłowy adres URL bez zmiany znaczenia w tagu kotwicy. Jeśli Twój program używa tych adresów URL do pobierania większej liczby zasobów, OpenURI będzie narzekać, że adresy URL są nieprawidłowe. Musisz URI::escapeto zrobić, aby był prawidłowym adresem URL. Jest więc używany do zmiany znaczenia całego ciągu URI, aby był poprawny. Moim słowem URI :: unescape czyni adres URL czytelnym dla człowieka, a URI :: escape czyni go poprawnym dla przeglądarek.
To jest termin mojego laika i nie krępuj się go poprawić.
Różnica polega na tym, że URI.escape nie działa ...
CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"
URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
CGI.escape służy do zmiany znaczenia adresu URL w ciągu zapytania. Wszystkie znaki, które nie należą do ALPHA, DIGIT, '_', '-', ''. i zestaw znaków „” są chronione.
Ale to spowodowałoby, że adres URL byłby nieprawidłowy, ponieważ adres URL musi zawierać znaki „/”, „:”, „?”, „[”, „&”, „=” I „;”. Może więcej, niż nie mogę wymyślić z czubka głowy.
URI.escape pozostawia te znaki adresu URL w spokoju i próbuje znaleźć klucze ciągu zapytania i wartości, które mają zostać usunięte. Jednak naprawdę nie można na tym polegać, ponieważ wartości mogą mieć różne rodzaje znaków, uniemożliwiające łatwą ucieczkę. Zasadniczo jest już za późno. Ale jeśli można polegać na prostocie adresu URL (brak znaków „&” i „=” itp. W wartościach), ta funkcja może zostać użyta do uniknięcia być może nieczytelnych lub niedozwolonych znaków.
Ogólnie - zawsze używaj CGI.escape na poszczególnych kluczach i wartościach przed połączeniem ich za pomocą „&” i dodaniem ich po „?”.
CGI.escape nie działał z API OpenProject. Zakodował [], a nie +. Zhakowałem to razem, co wydaje się działać do tej pory dla API OpenProject. Ale jestem pewien, że brakuje niektórych plików .gsub. Prawdopodobnie jest prawie tak zły, jak URI.escape, ale nie da ci przestarzałych błędów.
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\"]")
Oba wyjścia:
=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart% 22] "