Hoy en el trabajo me he encontrado con “un bug en Java e Internetes”. Bueno, más que un bug es un comportamiento extraño por especificaciones obsoletas, implementaciones independientes de contexto etc. etc. Pero es algo que te puedes encontrar en la vida real, así que he pensado que sería interesante contarlo.
El problema se da al leer un documento HTML con Java y tener que interpretar las direcciones relativas que contiene dicho documento. Si una de las direcciones únicamente contiene un “query string”... ¿Cómo la interpretarías vosotros?
Es decir, si en la página www.host.com/dir/loquesea.do encontramos un enlace tal que así href=”?param=value”... ¿Dónde ha de ir la página?
La respuesta correcta es “depende” :).
- Si estamos hablando de HTML 4.1, la respuesta es www.host.com/dir/loquesea.do?param=value y si hacéis una prueba con el navegador, lo debería resolver así.
- En cambio... ¿qué ocurre si procesáis ese documento con Java y usáis java.net.Uri.resolve(relativePath) para obtener la nueva URL? El resultado es www.host.com/dir/?param=value
¿Y cual de las dos respuestas es incorrecta? En realidad “ninguna”. La clase java.net.Uri implementa correctamente la resolución de caminos relativos según la RFC2396, de agosto de 1998, y por ello elimina el “loquesea.do” antes de añadir el camino relativo. En cambio HTML 4.1 está basado en la especificación RFC1808, de junio de 1995, la cual dice que si hay “query string” se mantiene la dirección completa como base. Lo curioso es que HTML 4.1 es de diciembre de 1999, más de un año después de que la RFC1808 fuera “sobre-escrita” por la RFC2396 pero sin embargo, parece al escribir la especificación de HTML no se fijaron en que la RFC1808 ya no estaba en vigor. De todas formas, el comportamiento de los navegadores es correcto ya que HTML 4.1 se basa en la RFC1808 y ésta es la que hay que seguir. Y la clase java.net.Uri tampoco hace nada “incorrecto” ya que en realidad sigue una especificación más reciente. En realidad podría hacerlo “mejor” si permitiera especificar si el método resolve() ha de funcionar según HTML 4.1 o el futuro HTML 5, y puestos a tener un comportamiento por defecto... HTML 4.1 es muy común.... en fin, que la cosa es bastante ambigua así que la mejor solución es no escribir nunca enlaces de esa forma y escribirlos al menos un poco más explícitos, o si hay que tratar en Java las páginas HTML que escribe un tercero... si esas páginas son HTML 4.1 hay que tener en cuenta que java.net.Uri no resuelve las direcciones relativas como lo hacen los navegadores, así que hay que tratar la dirección antes de pasársela para obtener el resultado esperado.
Y ahí queda escrito ese aviso para navegantes, por si a alguien le ahorra un buen rato de investigación leyendo especificaciones y el código del OpenJDK como he tenido que hacer yo.
Happy coding! EJ
No hay comentarios:
Publicar un comentario