Codage des paramètres de requête d'URL en Java

108

Comment encoder les paramètres de requête pour aller sur une URL en Java? Je sais, cela semble être une question évidente et déjà posée.

Il y a deux subtilités dont je ne suis pas sûr:

  1. Les espaces doivent-ils être encodés sur l'URL sous la forme "+" ou "% 20"? Dans Chrome, si je tape "http://google.com/foo=?bar me", Chrome le modifie pour qu'il soit encodé avec% 20
  2. Est-il nécessaire / correct de coder les deux points ":" comme% 3B? Chrome ne le fait pas.

Remarques:

  • java.net.URLEncoder.encodene semble pas fonctionner, il semble que ce soit pour le codage des données à soumettre. Par exemple, il encode l'espace comme +au lieu de %20et encode deux-points, ce qui n'est pas nécessaire.
  • java.net.URI n'encode pas les paramètres de requête
Alex Black
la source
Cette question semble utile: stackoverflow.com/questions/444112/…
Alex Black
2
la structure de la partie requête dépend du serveur, bien que la plupart s'attendent à application/x-www-form-urlencodeddes paires clé / valeur. Voir ici pour en savoir plus : legalargumentexception.blogspot.com/2009/12/…
McDowell

Réponses:

127

java.net.URLEncoder.encode(String s, String encoding)peut aussi aider. Il suit l'encodage du formulaire HTML application/x-www-form-urlencoded.

URLEncoder.encode(query, "UTF-8");

D'autre part, l' encodage en pourcentage (également appelé encodage URL ) encode l'espace avec %20. Deux- :points est un caractère réservé, il restera donc toujours des deux points, après l'encodage.

Buhake Sindi
la source
3
J'ai mentionné que je ne pensais pas que l'encodage d'url était fait, mais plutôt les données à soumettre via un formulaire. commentaires?
Alex Black
C'est parce qu'il URLEncoderest conforme au application/x-www-form-urlencodedformat MIME (qui est un encodage de formulaire HTML valide). Je suppose que ce n'est pas ce que vous recherchez.
Buhake Sindi
6
J'ai fini par utiliser URLEncoder.encode et remplacer "+" par "% 20"
Alex Black
2
Il encode les barres obliques en "% 2F", ne devrait-il pas laisser les barres obliques d'URL telles qu'elles sont?
golimar
6
@golimar Non, ça ne devrait pas. Vous êtes censé lui donner une valeur de paramètre uniquement et non l'URL entière. Prenons l'exemple http://example.com/?url=http://example.com/?q=c&sort=name. Doit-il encoder &sort=nameou non? Il n'y a aucun moyen de distinguer la valeur de l'URL. C'est la raison exacte pour laquelle vous avez besoin d'un encodage de valeur en premier lieu.
Pijusn
15

EDIT: URIUtiln'est plus disponible dans les versions plus récentes, meilleure réponse à Java - encoder l'URL ou par M. Sindi dans ce fil.


URIUtild'Apache httpclient est vraiment utile, bien qu'il existe des alternatives

URIUtil.encodeQuery(url);

Par exemple, il encode l'espace comme "+" au lieu de "% 20"

Les deux sont parfaitement valables dans le bon contexte . Bien que si vous préférez vraiment, vous pouvez émettre une chaîne de remplacement.

Johan Sjöberg
la source
Je suis d'accord. Utilisez HttpClient, vous serez beaucoup plus heureux.
DaShaun
Ce look prometteur, vous avez un lien par hasard? Je cherche sur Google mais j'en trouve beaucoup.
Alex Black
1
Cette méthode ne semble pas être présente dans HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black
@Alex, hmm c'est ennuyeux, j'ai toujours utilisé cette routine avec de bons résultats. Une idée est de récupérer le code source de la version 3, car ils ne voulaient évidemment plus le maintenir.
Johan Sjöberg
1
URIUtil.encodeWithinQueryest ce que vous utiliseriez pour encoder un paramètre de requête individuel, ce que la question d'origine semblait poser.
Jesse Glick
13

Malheureusement, URLEncoder.encode () ne produit pas de codage en pourcentage valide (comme spécifié dans la RFC 3986 ).

URLEncoder.encode () encode tout très bien, sauf que l' espace est encodé en "+". Tous les encodeurs URI Java que j'ai pu trouver n'exposent que des méthodes publiques pour encoder la requête, le fragment, les parties de chemin, etc. - mais n'exposent pas l'encodage «brut». C'est malheureux car le fragment et la requête sont autorisés à coder l'espace en +, nous ne voulons donc pas les utiliser. Le chemin est codé correctement mais est d'abord «normalisé», nous ne pouvons donc pas non plus l'utiliser pour un codage «générique».

Meilleure solution que je pourrais trouver:

return URLEncoder.encode(raw, "UTF-8").replaceAll("\\+", "%20");

Si replaceAll()c'est trop lent pour vous, je suppose que l'alternative est de rouler votre propre encodeur ...

EDIT: J'ai eu ce code ici en premier qui n'encode pas "?", "&", "=" Correctement:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);
Kosta
la source
+est un encodage parfaitement valide d'un espace.
Lawrence Dol
@LawrenceDol c'est vrai mais parfois +peut être mal interprété - jetez un œil à C # blogs.msdn.microsoft.com/yangxind/2006/11/08/…
Lu55
Ce. J'ai comparé diverses alternatives à la encodeURIComponentsortie de la méthode Javascript , et c'était la seule correspondance exacte pour celles que j'ai essayées (requêtes avec des espaces, des caractères spéciaux turcs et allemands).
Utku Özdemir
8

Il n'est pas nécessaire de coder un deux-points en tant que% 3B dans la requête, bien que cela ne soit pas illégal.

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Il semble également que seuls les espaces codés en pourcentage soient valides, car je doute que l'espace soit un ALPHA ou un DIGIT

consultez la spécification URI pour plus de détails.

Edwin Buck
la source
Mais cela peut changer la signification de l'URI, puisque l'interprétation de la chaîne de requête appartient au serveur. Si vous produisez une application/x-www-form-urlencodedchaîne de requête, l'un ou l'autre convient. Si vous corrigez une URL que l'utilisateur a tapée / collée, elle :doit rester seule.
tc.
@tc. Vous avez raison, si deux points sont utilisés comme délimiteur général (page 12 de la RFC); cependant, s'il n'est pas utilisé comme délimiteur général, les deux codages doivent se résoudre de la même manière.
Edwin Buck
Vous devez également faire attention car les URL ne sont pas vraiment un sous-ensemble d'URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent
5

L'URLEncoder Java intégré fait ce qu'il est censé faire, et vous devriez l'utiliser.

Un "+" ou "% 20" sont tous deux des remplacements valides pour un caractère d'espace dans une URL. L'un ou l'autre fonctionnera.

Un ":" doit être codé, car c'est un caractère de séparation. ie http: // toto ou ftp: // bar . Le fait qu'un navigateur particulier puisse le gérer lorsqu'il n'est pas codé ne le rend pas correct. Vous devez les encoder.

Par bonne pratique, veillez à utiliser la méthode qui prend un paramètre de codage de caractères. UTF-8 y est généralement utilisé, mais vous devez le fournir explicitement.

URLEncoder.encode(yourUrl, "UTF-8");
rfeak
la source
5
+n'est qu'une représentation de l'espace dans application/x-www-form-urlencoded; il n'est pas garanti de fonctionner même lorsqu'il est limité à HTTP. De même, :est valide dans une chaîne de requête et ne doit pas être converti en %3B; un serveur peut choisir de les interpréter différemment.
tc.
1
cette méthode encode également des barres obliques entiers url et d' autres personnages qui font partie par exemple http://à ce http%3A%2F%2Fqui est inexact
Pour Kra
2
@ToKra vous n'êtes pas censé encoder la http://pièce. La méthode concerne les paramètres de requête et les données de formulaire codées. Si, cependant, vous vouliez passer l'URL d'un autre site Web en tant que paramètre de requête, ALORS vous voudrez l'encoder pour éviter de confondre l'analyseur d'URL.
beldaz
@tc Ma lecture de w3.org/TR/html4/interact/forms.html#h-17.13.3.3 est que toutes les données du formulaire GET sont codées en tant que application/x-www-form-urlencodedtype de contenu. Cela ne signifie-t-il pas que cela doit fonctionner pour HTTP?
beldaz
0

si vous avez seulement un problème d'espace dans l'url. J'ai utilisé le code ci-dessous et cela fonctionne bien

String url;
URL myUrl = new URL(url.replace(" ","%20"));

exemple: l'url est

www.xyz.com?para=hello monsieur

alors la sortie de muUrl est

www.xyz.com?para=hello%20sir

Jignesh Patel
la source
0
String param="2019-07-18 19:29:37";
param="%27"+param.trim().replace(" ", "%20")+"%27";

J'ai observé en cas de Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")ne fonctionne pas.

ICL Ventes EXIMON
la source