Passer des variables à JavaScript dans ExpressJS
je suis complètement perdu sur ceci; j'utilise NodeJS pour aller chercher un JSON et je dois passer la variable à ma page et 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); en utilisant maintenant EJS je veux recueillir ces données que je sais pour rendre sur la page est tout simplement
<%= myVar %>
mais je dois être en mesure de recueillir 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 que j'ai essayé
En Jade c'est comme alert('!{myVar}')
ou !{JSON.stringify(myVar)}
. Puis-je faire quelque chose de semblable dans les SEJ? Je n'ai pas besoin d'un champ comme <input type=hidden>
et prendre la valeur du champ en javascript. Si quelqu'un peut aider beaucoup apprécié
6 réponses
vous pouvez utiliser ce (côté client):
<script>
var myVar = <%- JSON.stringify(myVar) %>;
</script>
vous pouvez aussi demander à EJS de rendre 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
) aurait encore besoin de l'extension .html
, sinon EJS ne le trouvera pas (à moins que vous ne le disiez à Express).
comme @ksloan le souligne dans les commentaires: vous devez faire attention à ce que myVar
contient. Si elle contient contenu généré par les utilisateurs, cela peut laisser votre site ouvert pour des attaques par injection de script.
Une solution possible pour empêcher que cela se passe:
<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é ici est d'éviter les risques XSS si myVar contient des citations, 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 guillemets ou aux balises HTML puisque Base64 ne contient que des caractères "sûrs" à mettre dans une chaîne de caractères Citée.
la solution que je propose:
fichier EJS:
<script>
var myVar = <%- passValue(myVar) %>
</script>
qui rendra dans 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 utiliser un autre si vous préférez mais faites attention s'il supporte 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}}
essayez ceci:
<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
selon la documentation ici :
Aller à la Dernière Version , à télécharger ./ ejs.js ou ./ ejs.min.js.
incluez l'un de ceux-ci 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 un double devis sans escapade. Alors mieux vaut traverser obj et échapper à chaque propriété string.
, 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 ejs vous avez 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 est en toute sécurité avec la syntaxe sans escapade
window.product = <%-JSON.stringify(encodedProduct)%>;