Codificación de parámetros de consulta de URL en Java

108

¿Cómo se codifican los parámetros de consulta para ir a una URL en Java? Lo sé, esto parece una pregunta obvia y ya hecha.

Hay dos sutilezas de las que no estoy seguro:

  1. ¿Deben codificarse los espacios en la URL como "+" o como "% 20"? En Chrome, si escribo "http://google.com/foo=?bar me", Chrome lo cambia para que se codifique con% 20
  2. ¿Es necesario / correcto codificar los dos puntos ":" como% 3B? Chrome no lo hace.

Notas:

  • java.net.URLEncoder.encodeno parece funcionar, parece ser para que los datos de codificación se envíen desde el formulario. Por ejemplo, codifica espacio como en +lugar de %20y codifica dos puntos que no es necesario.
  • java.net.URI no codifica parámetros de consulta
Alex negro
fuente
Esta pregunta parece útil: stackoverflow.com/questions/444112/…
Alex Black
2
la estructura de la parte de consulta depende del servidor, aunque la mayoría espera application/x-www-form-urlencodedpares clave / valor. Vea aquí para más información: illegalargumentexception.blogspot.com/2009/12/…
McDowell

Respuestas:

127

java.net.URLEncoder.encode(String s, String encoding)también puede ayudar. Sigue la codificación del formulario HTML application/x-www-form-urlencoded.

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

Por otro lado, la codificación porcentual (también conocida como codificación de URL ) codifica el espacio con %20. Los :dos puntos son un carácter reservado, por lo que seguirán siendo dos puntos después de la codificación.

Buhake Sindi
fuente
3
Mencioné que no pensé que eso codificara la URL, sino que codifica los datos para enviarlos a través de un formulario. comentarios?
Alex Black
Eso es porque URLEncoderse ajusta al application/x-www-form-urlencodedformato MIME (que es una codificación de formulario HTML válida). Supongo que eso no es lo que estás buscando.
Buhake Sindi
6
Terminé usando URLEncoder.encode y reemplazando "+" con "% 20"
Alex Black
2
Codifica barras en "% 2F", ¿no debería dejar las barras como están?
golimar
6
@golimar No, no debería. Se supone que debe darle solo el valor del parámetro y no la URL completa. Considere el ejemplo http://example.com/?url=http://example.com/?q=c&sort=name. ¿Debería codificar &sort=nameo no? No hay forma de distinguir el valor de la URL. Esa es la razón exacta por la que necesita la codificación de valores en primer lugar.
Pijusn
15

EDITAR: URIUtilya no está disponible en versiones más recientes, mejor respuesta en Java - codificar URL o por Mr. Sindi en este hilo.


URIUtilde Apache httpclient es realmente útil, aunque existen algunas alternativas

URIUtil.encodeQuery(url);

Por ejemplo, codifica el espacio como "+" en lugar de "% 20".

Ambos son perfectamente válidos en el contexto adecuado . Aunque si realmente lo prefiere, puede emitir un reemplazo de cadena.

Johan Sjöberg
fuente
Tendría que estar de acuerdo. Utilice HttpClient, será mucho más feliz.
DaShaun
Esa mirada prometedora, ¿consiguió un vínculo por casualidad? Estoy buscando en Google, pero encuentro muchos.
Alex Black
1
¿Este método no parece estar presente en HttpClient 4.1? hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Alex Black
@Alex, hmm eso es molesto, siempre he usado esa rutina con buenos resultados. Una idea es tomar el código fuente de la versión 3, ya que ahora obviamente ya no querían mantenerlo.
Johan Sjöberg
1
URIUtil.encodeWithinQueryes lo que usaría para codificar un parámetro de consulta individual, que es lo que parecía estar preguntando la pregunta original.
Jesse Glick
13

Desafortunadamente, URLEncoder.encode () no produce una codificación de porcentaje válida (como se especifica en RFC 3986 ).

URLEncoder.encode () codifica todo muy bien, excepto que el espacio está codificado en "+". Todos los codificadores URI de Java que pude encontrar solo exponen métodos públicos para codificar la consulta, el fragmento, las partes de la ruta, etc., pero no exponga la codificación "cruda". Esto es lamentable, ya que se permite que el fragmento y la consulta codifiquen el espacio en +, por lo que no queremos usarlos. La ruta está codificada correctamente, pero primero se "normaliza", por lo que tampoco podemos usarla para la codificación "genérica".

La mejor solución que se me ocurrió:

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

Si replaceAll()es demasiado lento para ti, supongo que la alternativa es rodar tu propio codificador ...

EDITAR: Primero tenía este código aquí que no codifica "?", "&", "=" Correctamente:

//don't use - doesn't properly encode "?", "&", "="
new URI(null, null, null, raw, null).toString().substring(1);
Kosta
fuente
+es una codificación perfectamente válida de un espacio.
Lawrence Dol
@LawrenceDol es cierto, pero a veces +se puede interpretar incorrectamente; eche un vistazo a C # blogs.msdn.microsoft.com/yangxind/2006/11/08/…
Lu55
Esta. Comparé varias alternativas con la encodeURIComponentsalida del método de Javascript , y esta fue la única coincidencia exacta para las que probé (consultas con espacios, caracteres especiales turcos y alemanes).
Utku Özdemir
8

No es necesario codificar dos puntos como% 3B en la consulta, aunque hacerlo no es ilegal.

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

También parece que solo los espacios codificados por porcentaje son válidos, ya que dudo que el espacio sea un ALPHA o un DÍGITO

consulte la especificación de URI para obtener más detalles.

Edwin Buck
fuente
Pero hacerlo puede cambiar el significado del URI, ya que la interpretación de la cadena de consulta depende del servidor. Si está produciendo una application/x-www-form-urlencodedcadena de consulta, cualquiera de las dos está bien. Si está arreglando una URL que el usuario escribió / pegó, :debe dejarlo solo.
tc.
@tc. Tiene razón, si los dos puntos se utilizan como delimitador general (página 12 del RFC); sin embargo, si no se utiliza como delimitador general, ambas codificaciones deben resolverse de forma idéntica.
Edwin Buck
También debe tener cuidado ya que las URL no son realmente un subconjunto de URI: adamgent.com/post/25161273526/urls-are-not-a-subset-of-uris
Adam Gent
5

El URLEncoder de Java integrado está haciendo lo que se supone que debe hacer, y debería usarlo.

Un "+" o "% 20" son ambos reemplazos válidos para un carácter de espacio en una URL. Cualquiera de los dos funcionará.

Un ":" debe estar codificado, ya que es un carácter separador. es decir, http: // foo o ftp: // bar . El hecho de que un navegador en particular pueda manejarlo cuando no está codificado no lo hace correcto. Deberías codificarlos.

Como una buena práctica, asegúrese de utilizar el método que toma un parámetro de codificación de caracteres. UTF-8 generalmente se usa allí, pero debe proporcionarlo explícitamente.

URLEncoder.encode(yourUrl, "UTF-8");
rfeak
fuente
5
+es solo una representación del espacio en application/x-www-form-urlencoded; no se garantiza que funcione incluso cuando está restringido a HTTP. De manera similar, :es válido en una cadena de consulta y no debe convertirse a %3B; un servidor puede optar por interpretarlos de manera diferente.
tc.
1
este método también codifica barras completas de URL y otros caracteres que forman parte, por ejemplo, http://de lo http%3A%2F%2Fque no es correcto
Para Kra
2
@ToKra, se supone que no debes codificar la http://pieza. El método es para parámetros de consulta y datos de formulario codificados. Sin embargo, si desea pasar la URL de otro sitio web como parámetro de consulta, ENTONCES querrá codificarlo para evitar confundir el analizador de URL.
Beldaz
@tc Mi lectura de w3.org/TR/html4/interact/forms.html#h-17.13.3.3 es que todos los datos del formulario GET están codificados como application/x-www-form-urlencodedtipo de contenido. ¿No significa eso que debe funcionar para HTTP?
beldaz
0

si solo tiene un problema de espacio en la URL. He usado el siguiente código y funciona bien

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

ejemplo: la URL es

www.xyz.com?para=hello señor

entonces la salida de muUrl es

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

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

Observé en caso de que Datetime (Timestamp) URLEncoder.encode(param,"UTF-8")no funcione.

Ventas ICL EXIMON
fuente