Was ist der Unterschied zwischen URI.escape
und CGI.escape
und welchen soll ich verwenden?
Was ist der Unterschied zwischen URI.escape
und CGI.escape
und welchen soll ich verwenden?
Antworten:
Es gab einige kleine Unterschiede, aber der wichtige Punkt ist, dass URI.escape
er in Ruby 1.9.2 veraltet ist ... also benutze CGI::escape
oder ERB :: Util.url_encode .
Für Interessierte gibt es eine lange Diskussion über Ruby-Core, in der auch WEBrick :: HTTPUtils.escape und WEBrick :: HTTPUtils.escape_form erwähnt werden .
ERB::Util.url_encode
, die ordnungsgemäß %20
für Leerzeichen verwendet wird
Was ist der Unterschied zwischen einer Axt und einem Schwert und welches sollte ich verwenden? Nun, es hängt davon ab, was Sie tun müssen.
URI.escape
sollte eine Zeichenfolge (URL) in die sogenannte " Prozentcodierung " codieren .
CGI::escape
stammt aus der CGI- Spezifikation, die beschreibt, wie Daten zwischen Webserver und Anwendung codiert / decodiert werden sollen.
Angenommen, Sie müssen einem URI in Ihrer App entkommen. Es ist ein spezifischerer Anwendungsfall. Dafür nutzte die Ruby-Community URI.escape
jahrelang. Das Problem dabei URI.escape
war, dass die RFC-3896-Spezifikation nicht verarbeitet werden konnte.
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
wurde als veraltet markiert:
Darüber hinaus ist der aktuelle URI.encode einfach gsub. Aber ich denke, es sollte eine URI in Komponenten aufteilen, dann jede Komponente maskieren und sie schließlich verbinden.
Der aktuelle URI.encode wird daher als schädlich und veraltet angesehen. Dies wird entfernt oder das Verhalten drastisch geändert.
Was ist der Ersatz zu diesem Zeitpunkt?
Wie oben erwähnt, ist der aktuelle URI.encode auf Spezifikationsebene falsch. Wir werden also nicht den genauen Ersatz liefern. Der Austausch variiert je nach Anwendungsfall.
Leider gibt es in den Dokumenten kein einziges Wort darüber. Die einzige Möglichkeit, dies zu erfahren, besteht darin, die Quelle zu überprüfen oder das Skript mit Warnungen in ausführlicher Ebene ( -wW2
) auszuführen (oder Google-Fu zu verwenden).
Einige schlugen vor , CGI::Escape
für Abfrageparameter zu verwenden , da Sie einem gesamten URI nicht entkommen konnten:
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
sollte nur für Abfrageparameter verwendet werden, aber die Ergebnisse stimmen wieder mit der Spezifikation überein. Tatsächlich ist der häufigste Anwendungsfall das Entkommen von Formulardaten, z. B. beim Senden einer application/x-www-form-urlencoded
POST-Anforderung.
Ebenfalls erwähnt WEBrick::HTTPUtils.escape
wird keine große Verbesserung (wieder ist es nur eine einfache gsub
, was IMO sogar eine schlechtere Option ist als 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"
Das der Spezifikation am nächsten liegende scheint das adressierbare Juwel zu sein:
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"
Beachten Sie, dass Addressable im Gegensatz zu allen vorherigen Optionen nicht maskiert #
wird und dies das erwartete Verhalten ist. Sie möchten den #
Hash im URI-Pfad behalten, jedoch nicht in der URI-Abfrage.
Das einzige verbleibende Problem ist, dass wir unseren Abfrageparametern nicht richtig entkommen konnten, was uns zu dem Schluss bringt: Wir sollten nicht eine einzige Methode für den gesamten URI verwenden, da es (bisher) keine perfekte Lösung gibt. Wie Sie sehen, &
wurde nicht aus "Mein Blog & Ihr Blog" entkommen. Wir müssen für Abfrageparameter eine andere Form der Escape-Funktion verwenden, bei der Benutzer verschiedene Zeichen einfügen können, die in URLs eine besondere Bedeutung haben. Geben Sie die URL-Codierung ein. Die URL-Codierung sollte für jeden "verdächtigen" Abfragewert verwendet werden, ähnlich wie ERB::Util.url_encode
folgt:
ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""
Es ist cool, aber wir haben bereits Addressable benötigt:
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"
Fazit:
URI.escape
oder ähnlichesCGI::escape
Sie diese Option, wenn Sie nur eine Formularflucht benötigenAddressable
eines Ihrer Juwelen zu haben, können Sie zuerst die URL analysieren, z. B. rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Addressable:URL
, Sie können dann alle Instanzmethoden darauf aufrufen, vielleicht wird eine von ihnen die gewünschten Ergebnisse erhalten: rubydoc.info/gems/addressable/Addressable/URI
URI.escape verwendet einen zweiten Parameter, mit dem Sie markieren können, was unsicher ist. Siehe APIDock:
CGI::escape
ist gut für das Escape-Text-Segment geeignet, damit sie in URL-Abfrageparametern (Zeichenfolgen nach '?') verwendet werden können. Wenn Sie beispielsweise einen Parameter mit Schrägstrichen in der URL haben möchten, maskieren Sie CGI :: diese Zeichenfolge zuerst und fügen Sie sie dann in die URL ein.
In Rails werden Sie es jedoch wahrscheinlich nicht direkt verwenden. Normalerweise verwenden Sie hash.to_param
, die CGI::escape
unter der Haube verwendet werden.
URI::escape
ist gut, um einer URL zu entkommen, die nicht richtig maskiert wurde. Beispielsweise geben einige Websites eine falsche / nicht entführte URL in ihrem Ankertag aus. Wenn Ihr Programm diese URLs verwendet, um mehr Ressourcen abzurufen, beschwert sich OpenURI darüber, dass die URLs ungültig sind. Du brauchstURI::escape
diese, um eine gültige URL zu erstellen. Es wird also verwendet, um die gesamte URI-Zeichenfolge zu maskieren, damit sie korrekt ist. In meinem Wort macht URI :: unescape eine URL für den Menschen lesbar, und URI :: Escape macht sie für Browser gültig.
Dies ist der Begriff meines Laien und Sie können ihn gerne korrigieren.
Der Unterschied ist, dass URI.escape nicht funktioniert ...
CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"
URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
CGI.escape dient zum Escapezeichen eines URL-Werts in der Abfragezeichenfolge. Alle Zeichen, die nicht in ALPHA, DIGIT, '_', '-', 'fallen.' und '' Zeichensatz werden maskiert.
Aber das würde eine URL falsch machen, da eine URL '/', ':', '?', '[', '&', '=' Und ';' haben muss. Vielleicht mehr, als ich mir vorstellen kann.
URI.escape lässt diese URL-Zeichen in Ruhe und versucht, die Schlüssel und Werte der Abfragezeichenfolge zu finden, die maskiert werden sollen. Dies kann jedoch nicht wirklich abhängig gemacht werden, da Werte alle Arten von Zeichen enthalten können, die ein leichtes Entkommen verhindern. Grundsätzlich ist es zu spät. Wenn die URL jedoch einfach sein kann (keine '&' s und '=' s usw. in den Werten), kann diese Funktion verwendet werden, um möglicherweise unlesbare oder unzulässige Zeichen zu umgehen.
Im Allgemeinen - verwenden Sie CGI.escape immer für die einzelnen Schlüssel und Werte, bevor Sie sie mit '&' verbinden und nach dem '?' Hinzufügen.
CGI.escape funktionierte nicht mit der OpenProject-API. Es codierte das []: und nicht das +. Ich habe dies zusammen gehackt, was bisher für die OpenProject-API zu funktionieren scheint. Aber ich bin sicher, es fehlen einige .gsub's. Es ist wahrscheinlich fast so schlimm wie URI.escape, aber es gibt Ihnen nicht die veralteten Fehler.
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\"]")
Beide Ausgaben:
=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart% 22] "