Quelle est la différence entre URI.escape
et CGI.escape
et lequel dois-je utiliser?
Quelle est la différence entre URI.escape
et CGI.escape
et lequel dois-je utiliser?
Réponses:
Il y avait quelques petites différences, mais le point important est qu'il URI.escape
est obsolète dans Ruby 1.9.2 ... alors utilisez CGI::escape
ou ERB :: Util.url_encode .
Il y a une longue discussion sur ruby-core pour les personnes intéressées qui mentionne également WEBrick :: HTTPUtils.escape et WEBrick :: HTTPUtils.escape_form .
ERB::Util.url_encode
correctement %20
pour les espaces
Quelle est la différence entre une hache et une épée et laquelle dois-je utiliser? Eh bien, cela dépend de ce que vous devez faire.
URI.escape
était censé encoder une chaîne (URL) dans, soi-disant, " encodage en pourcentage ".
CGI::escape
provient de la spécification CGI , qui décrit comment les données doivent être encodées / décodées entre le serveur Web et l'application.
Maintenant, disons que vous devez échapper à un URI dans votre application. C'est un cas d'utilisation plus spécifique. Pour cela, la communauté Ruby l'utilise URI.escape
depuis des années. Le problème avec URI.escape
était qu'il ne pouvait pas gérer la spécification 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
a été marqué comme obsolète:
De plus, URI.encode actuel est un simple gsub. Mais je pense qu'il devrait diviser un URI en composants, puis échapper à chaque composant et enfin les joindre.
Donc, URI.encode actuel est considéré comme dangereux et obsolète. Cela sera supprimé ou changera radicalement de comportement.
Quel est le remplacement en ce moment?
Comme je l'ai dit ci-dessus, le code URI.encode actuel est incorrect au niveau des spécifications. Nous ne fournirons donc pas le remplacement exact. Le remplacement variera selon son cas d'utilisation.
Malheureusement, il n'y a pas un seul mot à ce sujet dans la documentation, la seule façon de le savoir est de vérifier la source, ou d'exécuter le script avec des avertissements au niveau détaillé ( -wW2
) (ou d'utiliser un google-fu).
Certains ont proposé d'utiliser CGI::Escape
pour les paramètres de requête, car vous ne pouviez pas échapper à un URI entier:
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
ne doit être utilisé que pour les paramètres de requête, mais les résultats seront, encore une fois, contre les spécifications. En fait, le cas d'utilisation le plus courant est l'échappement des données du formulaire, par exemple lors de l'envoi d'une application/x-www-form-urlencoded
requête POST.
Il WEBrick::HTTPUtils.escape
est également mentionné qu'il n'y a pas beaucoup d'amélioration (encore une fois, c'est juste une simple gsub
, qui est, l'OMI, une option encore pire que 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"
Le plus proche de la spécification semble être le joyau adressable :
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"
Notez que contrairement à toutes les options précédentes, Addressable ne s'échappe pas #
, et c'est le comportement attendu. vous souhaitez conserver le #
hachage dans le chemin URI mais pas dans la requête URI.
Le seul problème qui reste est que nous n'avons pas échappé correctement à nos paramètres de requête, ce qui nous amène à la conclusion: nous ne devrions pas utiliser une seule méthode pour l'URI entier, car il n'y a pas de solution parfaite (jusqu'à présent). Comme vous le voyez, &
n'a pas été échappé de "Mon blog et votre blog". Nous devons utiliser une autre forme d'échappement pour les paramètres de requête, où les utilisateurs peuvent mettre différents caractères qui ont une signification particulière dans les URL. Entrez le code URL. L'encodage d'URL doit être utilisé pour chaque valeur de requête "suspecte", de la même manière que ERB::Util.url_encode
:
ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""
C'est cool mais nous avons déjà requis adressable:
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"
Conclusion:
URI.escape
ou similaireCGI::escape
si vous n'avez besoin que d'un échappement de formulaireAddressable
comme l'un de vos joyaux, vous pouvez d'abord analyser l'URL, fi rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Addressable:URL
, vous pouvez alors appeler toutes les méthodes d'instance dessus, peut-être que l'une d'elles obtiendra les résultats souhaités: rubydoc.info/gems/addressable/Addressable/URI
URI.escape prend un deuxième paramètre qui vous permet de marquer ce qui n'est pas sûr. Voir APIDock:
CGI::escape
est bon pour échapper des segments de texte afin qu'ils puissent être utilisés dans les paramètres de requête d'URL (chaînes après '?'). Par exemple, si vous voulez avoir un paramètre contenant des barres obliques dans l'url, vous CGI :: échappez d'abord cette chaîne, puis insérez-la dans l'url.
Cependant, dans Rails, vous ne l'utiliserez probablement pas directement. Habituellement, vous utilisez hash.to_param
, qui utilisera CGI::escape
sous le capot.
URI::escape
est bon pour échapper à une URL qui n'a pas été correctement échappée. Par exemple, certains sites Web affichent une URL incorrecte / non échappée dans leur balise d'ancrage. Si votre programme utilise ces URL pour récupérer plus de ressources, OpenURI se plaindra que les URL ne sont pas valides. Vous en avez besoin pour URI::escape
en faire une URL valide. Il est donc utilisé pour échapper à toute la chaîne URI pour la rendre correcte. Dans mon mot, URI :: unescape rend une URL lisible par l'homme, et URI :: escape la rend valide pour les navigateurs.
Ce sont les termes de mon profane et n'hésitez pas à les corriger.
La différence est que URI.escape ne fonctionne pas ...
CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"
URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
CGI.escape sert à échapper une valeur URL dans la chaîne de requête. Tous les caractères qui ne tombent pas dans ALPHA, DIGIT, '_', '-', '.' et le jeu de caractères «» est échappé.
Mais cela rendrait une URL incorrecte, car une URL doit avoir "/", ":", "?", "[", "&", "=" Et ";". Peut-être plus que je ne peux pas penser du haut de ma tête.
URI.escape laisse ces caractères URL seuls et essaie de trouver les clés de chaîne de requête et les valeurs à échapper. Cependant, cela ne peut vraiment pas être dépendant car les valeurs peuvent avoir toutes sortes de caractères empêchant une évasion facile. En gros, il est trop tard. Mais si l'URL peut être considérée comme simple (pas de «&» et «=», etc. dans les valeurs), cette fonction peut être utilisée pour échapper des caractères peut-être illisibles ou illégaux.
En général, utilisez toujours CGI.escape sur les clés et valeurs individuelles avant de les joindre avec «&» et de les ajouter après le «?».
CGI.escape ne fonctionnait pas avec l'API OpenProject. Il encodait le [] ,: et non le +. J'ai piraté cela ensemble, ce qui semble fonctionner jusqu'à présent pour l'API d'OpenProject. Mais je suis sûr qu'il manque quelques .gsub. C'est probablement presque aussi mauvais que URI.escape, mais cela ne vous donnera pas les erreurs obsolètes.
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\"]")
Les deux sorties:
=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart% 22] "