Tengo un error en algún código de legado y al tratar de solucionarlo me encontré con un comportamiento que no entiendo. La aplicación es una aplicación Spring MVC que utiliza JSP y JSTL. El siguiente es un ejemplo simplificado que reproduce el comportamiento que estoy hablando. El código de mi controlador es:
@GetMapping("/users/thing")
public ModelAndView thing() {
ModelAndView model = new ModelAndView("users/thing");
String stringWithApostrophe = "Any'String";
String escapedWithHtmlUtils = HtmlUtils.htmlEscape(stringWithApostrophe);
model.addObject("stringWithApostrophe", stringWithApostrophe);
model.addObject("escapedWithHtmlUtils", escapedWithHtmlUtils);
return model;
}
La variable stringWithApostrophe
tiene un carácter de apóstrofo dentro de ella, y luego escapar de ella y almacenar el valor escapado en otra variable. Después de eso añado los dos para el modelo.
Mi opinión es la siguiente:
<p><a onClick="clicked('${stringWithApostrophe}');" href="#">stringWithApostrophe: ${stringWithApostrophe}</a></p>
<p><a onClick="clicked('${escapedWithHtmlUtils}');" href="#">escapedWithHtmlUtils: ${escapedWithHtmlUtils}</a></p>
<script type="text/javascript">
function clicked(text){
console.log(text);
}
</script>
Si presiono CTRL+U
en mi navegador para ver la fuente de la página veo lo siguiente:
<p><a onClick="clicked('Any'String');" href="#">stringWithApostrophe: Any'String</a></p>
<p><a onClick="clicked('Any'String');" href="#">escapedWithHtmlUtils: Any'String</a></p>
... lo que se ve bien, y lo hace de esta manera:
... que es lo que esperaba demasiado. Cuando pulso en el primer eslabón falla también como era de esperar, la consola navegador muestra el mensaje de error Syntax error: missing ) after argument list
porque el apóstrofe sin escapar rompió el código Javascript.
Sin embargo, a pesar de que esperaba el segundo link para el trabajo, sino que también falla, con el mismo mensaje de error . ¿Por qué es este el caso? No puedo entenderlo, el apóstrofe se convierte en una entidad HTML como CTRL+U
muestra, por lo que no debe rompió el javascript. He estado buscando en Internet sobre las posibles causas para esto, pero no encontró nada. ¿Qué me estoy perdiendo?
Actualización : He subido el proyecto de ejemplo he usado para reproducir el error a Github, en caso de que sea útil.
Como se ha señalado en su pregunta, el apóstrofe se convirtió con éxito en una referencia de entidad HTML por la clase HtmlUtils a convertirse '
. El comportamiento que usted describe se produce porque las referencias a entidades HTML analizadores de resolver en los valores de atributo antes que el contenido se entrega al motor de JavaScript. La entidad en el onclick(...)
por lo tanto, la declaración se decodifica en el carácter original '
como se muestra a continuación.
onClick="clicked('Any'String');"
=> onClick="clicked('Any'String');"
.
Por lo tanto para el motor JS, las dos onClick(...)
sentencias son equivalentes.
Ver esta discusión relacionada discusión para más información sobre el tema.