pass - Pasar variables a JavaScript en ExpressJS
express render pass variable (6)
Estoy completamente perdido en esto; Estoy usando NodeJS para buscar un JSON y necesito pasar la variable a mi página y tener JavaScript para usar los datos.
app.get(''/test'', function(req, res) {
res.render(''testPage'', {
myVar: ''My Data''
});
Ese es mi código Express (muy simple para fines de prueba); ahora usando EJS quiero recopilar esta información que sé que debo representar en la página es simplemente
<%= myVar %>
Pero necesito poder recopilar estos datos en JavaScript (si es posible dentro de un archivo .js) pero por ahora solo para mostrar la variable en un cuadro de alerta que he intentado
En Jade, es como alert(''!{myVar}'')
o !{JSON.stringify(myVar)}
. ¿Puedo hacer algo similar en EJS? No necesito ningún campo como <input type=hidden>
y tomar el valor del campo en javascript. Si alguien puede ayudar, sea muy apreciado
En la solución aceptada, JSON.parse fallará si myVar tiene una propiedad con valor con comillas dobles sin guardar. Así que es mejor atravesar Obj y escapar de cada propiedad de cadena.
Aquí hay una función que cubre mi caso:
function traverseObj (obj, callback)
{
var result = {};
if ( !isArray(obj) && !isObject(obj) ) {
return callback(obj);
}
for ( var key in obj ) {
if ( obj.hasOwnProperty(key) ) {
var value = obj[key];
if (isMongoId(value)){
var newValue = callback(value.toString());
result[key] = newValue;
}
else if (isArray ( value) ) {
var newArr = [];
for ( var i=0; i < value.length; i++ ) {
var arrVal = traverseObj(value[i], callback);
newArr.push(arrVal);
}
result[key] = newArr;
}
else if ( isObject(value) ) {
result[key] = traverseObj(value, callback);
}
else {
var newValue = callback(value);
result[key] = newValue;
}
}
}
return result;
};
Que en ejs simplemente tienes que:
<%
var encodeValue = function(val) {
if ( typeof val === ''string'' ) {
return sanitizeXSS(val); //use some library (example npm install xss)
}
return val;
}
var encodedProduct = ejs_utils.traverseObj(product, encodeValue);
%>
y ahora puedes transportar de forma segura con sintaxis sin escapes
window.product = <%-JSON.stringify(encodedProduct)%>;
La principal dificultad aquí es evitar los riesgos de XSS si myVar contiene comillas, o </script>
por ejemplo. Para evitar este problema, propongo utilizar la codificación Base64 después de JSON.stringify. Esto evitaría todos los riesgos relacionados con las comillas o etiquetas HTML, ya que Base64 solo contiene caracteres "seguros" para poner en una cadena entrecomillada.
La solución que propongo:
Archivo EJS:
<script>
var myVar = <%- passValue(myVar) %>
</script>
que se convertirá en algo así como (por ejemplo aquí myVar = null):
<script>
var myVar = JSON.parse(Base64.decode("bnVsbA=="))
</script>
Server-side NodeJS:
function passValue(value) {
return ''JSON.parse(Base64.decode("'' + new Buffer(JSON.stringify(value)).toString(''base64'') + ''"))''
}
JS del lado del cliente (esta es una implementación de la decodificación Base64 que funciona con Unicode, puede usar otra si lo prefiere pero tenga cuidado si es compatible con Unicode):
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9/+///=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(//r/n/g,"/n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}
Por la documentación here :
Vaya a la última versión , descargue ./ejs.js o ./ejs.min.js.
Incluye uno de estos en tu página y ejs.render(str)
.
Prueba esto:
<script type="text/javascript">
window.addEventListener(''load'', function(){
alert(''<%= myVar %>'');
});
</script>
Puede usar esto (lado del cliente):
<script>
var myVar = <%- JSON.stringify(myVar) %>;
</script>
También puedes hacer que EJS renderice un archivo .js
:
app.get(''/test.js'', function(req, res) {
res.set(''Content-Type'', ''application/javascript'');
res.render(''testPage'', { myVar : ... });
});
Sin embargo, el archivo de plantilla ( testPage
) todavía necesitaría tener la extensión .html
, de lo contrario, EJS no lo encontrará (a menos que le indique a Express lo contrario).
Como señala @ksloan en los comentarios: debes tener cuidado con lo que myVar
contiene. Si contiene contenido generado por el usuario, esto puede dejar su sitio abierto para ataques de inyección de scripts.
Una posible solución para evitar que esto suceda:
<script>
function htmlDecode(input){
var e = document.createElement(''div'');
e.innerHTML = input;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
var myVar = JSON.parse(htmlDecode("<%= JSON.stringify(myVar) %>"));
</script>
si tiene objetos más complejos como una matriz, puede hacer esto:
<% if (myVar) { %>
<script>
myVar = JSON.parse(''<%- JSON.stringify(myVar) %>'');
</script>
<% } %>
de lo contrario, las soluciones anteriores que ha visto no funcionarán