Codifica dei parametri di query dell'URL in Java


108

Come si codificano i parametri di query per andare su un URL in Java? Lo so, questa sembra una domanda ovvia e già posta.

Ci sono due sottigliezze di cui non sono sicuro:

  1. Gli spazi devono essere codificati nell'URL come "+" o come "% 20"? In Chrome se digito "http://google.com/foo=?bar me", Chrome lo cambia per essere codificato con% 20
  2. È necessario / corretto codificare i due punti ":" come% 3B? Chrome no.

Appunti:

  • java.net.URLEncoder.encodenon sembra funzionare, sembra che sia per la codifica dei dati da inviare. Ad esempio, codifica lo spazio come +invece di %20e codifica i due punti che non è necessario.
  • java.net.URI non codifica i parametri di query

Questa domanda sembra utile: stackoverflow.com/questions/444112/…
Alex Black

2
la struttura della parte della query dipende dal server, sebbene la maggior parte si aspetti application/x-www-form-urlencodedcoppie chiave / valore. Vedi qui per ulteriori informazioni: illegaleargumentexception.blogspot.com/2009/12/…
McDowell

Risposte:


127

java.net.URLEncoder.encode(String s, String encoding)può aiutare anche. Segue la codifica del modulo HTML application/x-www-form-urlencoded.

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

D'altra parte, la codifica percentuale (nota anche come codifica URL ) codifica lo spazio con %20. I due punti sono un carattere riservato, quindi :rimarranno ancora i due punti, dopo la codifica.


3
Ho detto che non pensavo che facesse la codifica URL, invece codifica i dati da inviare tramite un modulo. Commenti?
Alex Black

Questo perché URLEncoderè conforme al application/x-www-form-urlencodedformato MIME (che è una codifica di modulo HTML valida). Suppongo che non sia quello che stai cercando.
Buhake Sindi

6
Ho finito per utilizzare URLEncoder.encode e sostituire "+" con "% 20"
Alex Black

2
Codifica le barre in "% 2F", non dovrebbe lasciare le barre dell'URL così come sono?
golimar

6
@golimar No, non dovrebbe. Dovresti dargli solo il valore del parametro e non l'intero URL. Considera l'esempio http://example.com/?url=http://example.com/?q=c&sort=name. Dovrebbe codificare &sort=nameo no? Non è possibile distinguere il valore dall'URL. Questo è il motivo esatto per cui hai bisogno della codifica del valore in primo luogo.
Pijusn

15

EDIT: URIUtilnon è più disponibile nelle versioni più recenti, risposta migliore su Java - codifica URL o da Mr. Sindi in questo thread.


URIUtildi Apache httpclient è davvero utile, sebbene ci siano alcune alternative

URIUtil.encodeQuery(url);

Ad esempio, codifica lo spazio come "+" invece di "% 20"

Entrambi sono perfettamente validi nel giusto contesto . Anche se se davvero preferissi potresti emettere una sostituzione di stringa.


Dovrei essere d'accordo. Usa HttpClient, sarai molto più felice.
DaShaun

Quello sguardo promettente, ha ottenuto un collegamento per caso? Sto cercando su Google ma ne trovo molti.
Alex Black

1
Questo metodo non sembra essere presente in HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black

@ Alex, hmm è fastidioso, ho sempre usato quella routine con buoni risultati. Un'idea è quella di prendere il codice sorgente dalla versione 3 poiché ora ovviamente non volevano più mantenerlo.
Johan Sjöberg

1
URIUtil.encodeWithinQueryè ciò che useresti per codificare un singolo parametro di query, che è ciò che sembrava chiedere la domanda originale.
Jesse Glick

13

Sfortunatamente, URLEncoder.encode () non produce una codifica percentuale valida (come specificato in RFC 3986 ).

URLEncoder.encode () codifica tutto bene, tranne spazio è codificato in "+". Tutti i codificatori URI Java che ho trovato espongono solo metodi pubblici per codificare la query, il frammento, le parti del percorso, ecc. - ma non esporre la codifica "grezza". Questo è sfortunato in quanto frammento e query possono codificare lo spazio in +, quindi non vogliamo usarli. Path è codificato correttamente ma viene prima "normalizzato", quindi non possiamo usarlo nemmeno per la codifica "generica".

La migliore soluzione che potrei trovare:

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

Se replaceAll() è troppo lento per te, immagino che l'alternativa sia rotolare il tuo codificatore ...

EDIT: ho avuto questo codice qui prima che non codifica "?", "&", "=" Correttamente:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);

+è una codifica perfettamente valida di uno spazio.
Lawrence Dol

@LawrenceDol è vero ma a volte +può essere interpretato in modo errato: dai un'occhiata a C # blogs.msdn.microsoft.com/yangxind/2006/11/08/…
Lu55

Questo. Ho confrontato varie alternative con l' encodeURIComponentoutput del metodo Javascript , e questa era l'unica corrispondenza esatta per quelle che ho provato (query con spazi, caratteri speciali turchi e tedeschi).
Utku Özdemir

8

Non è necessario codificare i due punti come% 3B nella query, anche se non è illegale.

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

Sembra anche che siano validi solo gli spazi codificati in percentuale, poiché dubito che lo spazio sia un ALPHA o un DIGIT

guarda la specifica URI per maggiori dettagli.


Ma così facendo si può cambiare il significato dell'URI, poiché l'interpretazione della stringa di query spetta al server. Se stai producendo una application/x-www-form-urlencodedstringa di query, entrambe vanno bene. Se stai correggendo un URL che l'utente ha digitato / incollato, :dovrebbe essere lasciato solo.
tc.

@tc. Hai ragione, se i due punti vengono utilizzati come delimitatori generali (pagina 12 dell'RFC); tuttavia, se non viene utilizzato come delimitatore generale, entrambe le codifiche dovrebbero risolversi in modo identico.
Edwin Buck

Devi anche fare attenzione perché gli URL non sono realmente un sottoinsieme di URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent

5

Il built in Java URLEncoder sta facendo quello che dovrebbe e dovresti usarlo.

Un "+" o "% 20" sono entrambi sostituzioni valide per uno spazio in un URL. Entrambi funzioneranno.

Un ":" dovrebbe essere codificato, poiché è un carattere separatore. cioè http: // foo o ftp: // bar . Il fatto che un particolare browser possa gestirlo quando non è codificato non lo rende corretto. Dovresti codificarli.

Come una questione di buona pratica, assicurati di utilizzare il metodo che accetta un parametro di codifica dei caratteri. UTF-8 è generalmente usato lì, ma dovresti fornirlo esplicitamente.

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

5
+è solo una rappresentazione dello spazio in application/x-www-form-urlencoded; non è garantito che funzioni anche se limitato a HTTP. Allo stesso modo, :è valido in una stringa di query e non deve essere convertito in %3B; un server può scegliere di interpretarli in modo diverso.
tc.

1
questo metodo codificare anche slash url integrali e altri personaggi che fanno parte ad esempio, http://per http%3A%2F%2Fi quali non è corretto
Per Kra

2
@ ToKra non dovresti codificare la http://parte. Il metodo è per i parametri di query e i dati del modulo codificato. Se, tuttavia, si desidera passare l'URL di un altro sito Web come parametro di query, ALLORA lo si vorrà codificare per evitare di confondere il parser dell'URL.
beldaz

@tc La mia lettura di w3.org/TR/html4/interact/forms.html#h-17.13.3.3 è che tutti i dati del modulo GET sono codificati come application/x-www-form-urlencodedtipo di contenuto. Non significa che deve funzionare per HTTP?
beldaz

0

se hai solo problemi di spazio nell'URL. Ho usato il codice seguente e funziona bene

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

esempio: l'URL è

www.xyz.com?para=hello signore

allora l'output di muUrl è

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


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

Ho notato che in caso di Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")non funziona.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.