Je suis complètement perdu à ce sujet; J'utilise NodeJS pour récupérer un fichier JSON et je dois transmettre la variable à ma page et laisser 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, il suffit d'essayer d'afficher la variable dans une zone d'alerte.
En Jade, c'est comme 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 je prends la valeur du champ en javascript. Si quelqu'un peut aider est très apprécié
Vous pouvez utiliser ceci (côté client):
<script>
var myVar = <%- JSON.stringify(myVar) %>;
</script>
Vous pouvez également demander à EJS de générer un fichier .js
:
app.get('/test.js', function(req, res) {
res.set('Content-Type', 'application/javascript');
res.render('testPage', { myVar : ... });
});
Cependant, le fichier de modèle (testPage
) doit toujours porter l'extension .html
, sinon EJS ne le trouvera pas (sauf indication contraire d'Express).
Comme @ksloan le fait remarquer dans les commentaires: vous devez faire attention à ce que contient myVar
. S'il contient du contenu généré par l'utilisateur, votre site peut rester ouvert aux attaques par injection de script.
Une solution possible pour éviter cela:
<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>
La principale difficulté consiste ici à éviter les risques XSS si myVar contient des guillemets, ou </script>
par exemple. Pour éviter ce problème, je propose d'utiliser Base64 encoding après JSON.stringify. Cela éviterait tous les risques liés aux guillemets ou aux balises HTML puisque Base64 ne contient que des caractères "sûrs" pour insérer une chaîne entre guillemets.
La solution que je propose:
Fichier EJS:
<script>
var myVar = <%- passValue(myVar) %>
</script>
qui rendra 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 (c'est une implémentation du décodage Base64 qui fonctionne avec Unicode, vous pouvez en utiliser une autre si vous préférez, mais soyez prudent 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}}
Essaye ça:
<script type="text/javascript">
window.addEventListener('load', function(){
alert('<%= myVar %>');
});
</script>
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
Voici comment je l'ai fait fonctionner, Dans le noeud js passe le json comme ceci
let j =[];
//sample json
j.Push({data:"hi});
res.render('index',{json:j});
maintenant en fonction js
var json = JSON.parse('<%- JSON.stringify(json) %>');
Cela a bien fonctionné pour moi
Dans la solution acceptée, JSON.parse échouera si myVar a une propriété avec une valeur avec guillemets doubles non échappés. 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;
};
Dans ejs, 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 en toute sécurité avec une syntaxe non échappée
window.product = <%-JSON.stringify(encodedProduct)%>;
Selon la documentation ici :
Allez à la Dernière version , téléchargez ./ejs.js ou ./ejs.min.js.
Incluez-en un sur votre page et ejs.render(str)
.