1. Introducción
En pocas palabras, la codificación de URL traduce los caracteres especiales de la URL a una representación que se adhiere a la especificación y se puede entender e interpretar correctamente.
En este artículo, nos centraremos en cómo codificar / decodificar la URL o los datos del formulario para que se adhiera a las especificaciones y se transmita a través de la red correctamente.
2. Analiza la URL
Una sintaxis básica de URI se puede generalizar como:
scheme:[//[user:[email protected]]host[:port]][/]path[?query][#fragment]
El primer paso para codificar un URI es examinar sus partes y luego codificar solo las partes relevantes.
Veamos un ejemplo de URI:
String testUrl = "//www.baeldung.com?key1=value+1&key2=value%40%21%242&key3=value%253";
Una forma de analizar el URI es cargar la representación de cadena en una clase java.net.URI :
@Test public void givenURL_whenAnalyze_thenCorrect() throws Exception { URI uri = new URI(testUrl); assertThat(uri.getScheme(), is("http")); assertThat(uri.getHost(), is("www.baeldung.com")); assertThat(uri.getRawQuery(), .is("key1=value+1&key2=value%40%21%242&key3=value%253")); }
La clase URI analiza la URL de representación de cadena y expone sus partes a través de una API simple, por ejemplo, getXXX.
3. Codifique la URL
Al codificar URI, uno de los errores comunes es codificar el URI completo. Normalmente, necesitamos codificar solo la parte de la consulta del URI.
Codifiquemos los datos usando el método encode (data, encodingScheme) de la clase URLEncoder :
private String encodeValue(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); } @Test public void givenRequestParam_whenUTF8Scheme_thenEncode() throws Exception { Map requestParams = new HashMap(); requestParams.put("key1", "value 1"); requestParams.put("key2", "[email protected]!$2"); requestParams.put("key3", "value%3"); String encodedURL = requestParams.keySet().stream() .map(key -> key + "=" + encodeValue(requestParams.get(key))) .collect(joining("&", "//www.baeldung.com?", "")); assertThat(testUrl, is(encodedURL));
El método de codificación acepta dos parámetros:
- datos - cadena a traducir
- encodingScheme - nombre de la codificación de caracteres
Este método de codificación convierte la cadena al formato application / x-www-form-urlencoded .
El esquema de codificación convertirá caracteres especiales en representación hexadecimal de dos dígitos de 8 bits que se representarán en forma de “ % xy ”. Cuando estamos tratando con parámetros de ruta o agregando parámetros que son dinámicos, codificaremos los datos y luego los enviaremos al servidor.
Nota: La recomendación del World Wide Web Consortium establece que se debe utilizar UTF-8 . No hacerlo puede introducir incompatibilidades. (Referencia: //docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html )
4. Decodifica la URL
Decodifiquemos ahora la URL anterior usando el método de decodificación del URLDecoder :
private String decode(String value) { return URLDecoder.decode(value, StandardCharsets.UTF_8.toString()); } @Test public void givenRequestParam_whenUTF8Scheme_thenDecodeRequestParams() { URI uri = new URI(testUrl); String scheme = uri.getScheme(); String host = uri.getHost(); String query = uri.getRawQuery(); String decodedQuery = Arrays.stream(query.split("&")) .map(param -> param.split("=")[0] + "=" + decode(param.split("=")[1])) .collect(Collectors.joining("&")); assertEquals( "//www.baeldung.com?key1=value 1&[email protected]!$2&key3=value%3", scheme + "://" + host + "?" + decodedQuery); }
Los dos bits importantes aquí son:
- analizar URL antes de decodificar
- utilizar el mismo esquema de codificación para codificar y decodificar
Si tuviéramos que decodificar que analizar, es posible que las partes de la URL no se analicen correctamente. Si usáramos otro esquema de codificación para decodificar los datos, resultaría en datos basura.
5. Codificar un segmento de ruta
URLEncoder no se puede utilizar para codificar el segmento de ruta de la URL . El componente de ruta se refiere a la estructura jerárquica que representa una ruta de directorio, o sirve para localizar recursos separados por "/" .
Los caracteres reservados en el segmento de la ruta son diferentes a los de los valores de los parámetros de consulta. Por ejemplo, un signo "+" es un carácter válido en un segmento de ruta y, por lo tanto, no debe codificarse.
Para codificar el segmento de ruta, usamos la clase UriUtils de Spring Framework en su lugar. La clase UriUtils proporciona los métodos encodePath y encodePathSegment para codificar la ruta y el segmento de ruta, respectivamente.
Veamos un ejemplo:
private String encodePath(String path) { try { path = UriUtils.encodePath(path, "UTF-8"); } catch (UnsupportedEncodingException e) { LOGGER.error("Error encoding parameter {}", e.getMessage(), e); } return path; }
@Test public void givenPathSegment_thenEncodeDecode() throws UnsupportedEncodingException { String pathSegment = "/Path 1/Path+2"; String encodedPathSegment = encodePath(pathSegment); String decodedPathSegment = UriUtils.decode(encodedPathSegment, "UTF-8"); assertEquals("/Path%201/Path+2", encodedPathSegment); assertEquals("/Path 1/Path+2", decodedPathSegment); }
En el fragmento de código anterior, podemos ver que cuando usamos el método encodePathSegment , devolvió el valor codificado y + no se codifica porque es un carácter de valor en el componente de ruta.
Agreguemos una variable de ruta a nuestra URL de prueba:
String testUrl = "/path+1?key1=value+1&key2=value%40%21%242&key3=value%253";
y para ensamblar y afirmar una URL codificada correctamente, cambiemos la prueba de la sección 2:
String path = "path+1"; String encodedURL = requestParams.keySet().stream() .map(k -> k + "=" + encodeValue(requestParams.get(k))) .collect(joining("&", "/" + encodePath(path) + "?", "")); assertThat(testUrl, CoreMatchers.is(encodedURL));
6. Conclusión
En este tutorial, hemos visto cómo codificar y decodificar los datos para que se puedan transferir e interpretar correctamente. Si bien el artículo se centró en la codificación / decodificación de valores de parámetros de consulta URI, el enfoque también se aplica a los parámetros de formulario HTML.
Puede encontrar el código fuente en GitHub.