Passer des variables à JavaScript dans ExpressJS

Je suis complètement perdu à ce sujet; J'utilise NodeJS pour récupérer un JSON et j'ai besoin de passer la variable à ma page et d'avoir JavaScript utiliser les données.

app.get('/test', function(req, res) { res.render('testPage', { myVar: 'My Data' }); 

C'est mon code Express (très simple à des fins de test); Maintenant en utilisant EJS Je veux rassembler ces données que je sais rendre sur la page est tout simplement

 <%= myVar %> 

Mais je dois pouvoir rassembler ces données en JavaScript (si possible dans un fichier .js) mais pour l'instant juste pour afficher la variable dans une boîte d'alerte, j'ai essayé

Dans Jade, c'est comme une alert('!{myVar}') ou !{JSON.stringify(myVar)} . Puis-je faire quelque chose de similaire dans EJS? Je n'ai besoin d'aucun champ comme <input type=hidden> et en prenant la valeur du champ en javascript. Si quelqu'un peut être très apprécié

Vous pouvez utiliser ce (côté client):

 <script> var myVar = <%- JSON.stringify(myVar) %>; </script> 

Vous pouvez également obtenir EJS pour rendre un fichier .js :

 app.get('/test.js', function(req, res) { res.set('Content-Type', 'application/javascript'); res.render('testPage', { myVar : ... }); }); 

Cependant, le fichier modèle ( testPage ) devrait toujours avoir l'extension .html , sinon, EJS ne le trouvera pas (sauf si vous le dites autrement).

Comme le mentionne @ksloan dans les commentaires: il faut faire attention à ce que myVar contient. S'il contient du contenu généré par l'utilisateur, cela peut laisser votre site ouvert pour les attaques par injection de script.

Une solution possible pour éviter que cela ne se produise:

 <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> 

Essaye ça:

 <script type="text/javascript"> window.addEventListener('load', function(){ alert('<%= myVar %>'); }); </script> 

La principale difficulté ici est d'éviter les risques XSS si myVar contient des devis, ou </script> par exemple. Pour éviter ce problème, je propose d'utiliser l'encodage Base64 après JSON.stringify. Cela éviterait tous les risques liés aux citations ou aux balises HTML puisque Base64 ne contient que des caractères «sûrs» pour mettre une chaîne citée.

La solution que je propose:

Fichier EJS:

 <script> var myVar = <%- passValue(myVar) %> </script> 

Qui se traduira par quelque chose comme (par exemple ici myVar = null):

 <script> var myVar = JSON.parse(Base64.decode("bnVsbA==")) </script> 

NodeJS côté serveur

 function passValue(value) { return 'JSON.parse(Base64.decode("' + new Buffer(JSON.stringify(value)).toString('base64') + '"))' } 

JS côté client (il s'agit d'une implémentation de décodage Base64 qui fonctionne avec Unicode, vous pouvez utiliser une autre si vous préférez, mais faites attention si elle prend en charge 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}} 

Si vous avez des objets plus complexes comme un tableau, vous pouvez le faire:

 <% if (myVar) { %> <script> myVar = JSON.parse('<%- JSON.stringify(myVar) %>'); </script> <% } %> 

Sinon, les solutions précédentes que vous avez vues ne fonctionneront pas

Selon la documentation ici :

Passez à la dernière version , téléchargez ./ejs.js ou ./ejs.min.js.

Incluez l'un de ces sur votre page, et ejs.render(str) .

Dans la solution acceptée, JSON.parse échouera si myVar a une propriété avec une valeur avec une double citation non modifiée. Donc mieux traverseObj et échappe à chaque propriété de chaîne.

Voici une fonction qui couvre mon cas:

 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 dans les ex, vous devez simplement:

 <% 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); %> 

Et maintenant vous pouvez transporter avec sécurité sans syntaxe

 window.product = <%-JSON.stringify(encodedProduct)%>;