2013-04-19 18 views
32

Sono completamente perso su questo; Sto usando NodeJS per recuperare un JSON e ho bisogno di passare la variabile alla mia pagina e ho JavaScript utilizzare i dati.Passa variabili a JavaScript in ExpressJS

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

Questo è il mio codice Express (molto semplice a scopo di test); ora utilizzando EJS voglio raccogliere questi dati che so di rendere sulla pagina è semplicemente

<%= myVar %> 

Ma ho bisogno di essere in grado di raccogliere questi dati in JavaScript (se possibile all'interno di un file .js), ma per il momento solo per visualizzare la variabile in una casella di avviso che ho provato

In Jade è come alert('!{myVar}') o !{JSON.stringify(myVar)}. Posso fare qualcosa di simile in EJS. Non ho bisogno di campi come <input type=hidden> e prendendo il valore del campo in javascript. Se qualcuno può aiutare molto apprezzato

risposta

58

si potrebbe usare questo (lato client):

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

Si potrebbe anche ottenere EJS per rendere un file .js:

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

Tuttavia, il file modello (testPage) dovrebbe ancora avere l'estensione .html, altrimenti EJS non la troverà (a meno che tu non dica Express altrimenti).

Come @ksloan indica nei commenti: è necessario fare attenzione a ciò che contiene myVar. Se contiene contenuti generati dagli utenti, questo potrebbe lasciare il tuo sito aperto per attacchi di script injection.

Una possibile soluzione per evitare che ciò accada:

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

btw, sono riuscito ad ottenere ejs a riconoscere un modello .js aggiungendo questo al mio server.js app.engine ('js', require ('ejs'). renderFile); –

+0

È anche possibile utilizzare alcune virgolette semplici ou circondano il codice. <% - JSON.stringify (myVar)%>; a "<% - JSON.stringify (myVar)%>;" – Ito

+1

fai attenzione, perché se myVar ha un utente che genera contenuti in esso, il tuo sito sarà vulnerabile agli attacchi XSS – ksloan

3

Prova questa:

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

Per la documentazione here:

Vai agli Latest Release, ./ejs.js download o ./ejs.min.js.

Includere uno di questi nella pagina e ejs.render(str).

1

se avete oggetti più complessi come un array, si può fare questo:

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

altrimenti, soluzioni precedenti avete visto non funzionerà

0

Nella soluzione accettata JSON.parse fallirà se myVar ha una proprietà con valore con doppia virgoletta senza escape. Quindi meglio attraversare Obj e sfuggire a ogni proprietà stringa.

Ecco una funzione che copre il mio 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; 
}; 

Che in ejs si deve semplicemente:

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

e ora è possibile il trasporto è in modo sicuro con la sintassi escape

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

La principale difficoltà qui consiste nell'evitare i rischi XSS se myVar contiene citazioni o </script> per esempio. Per evitare questo problema, propongo di utilizzare la codifica Base64 dopo JSON.stringify. Ciò eviterebbe tutti i rischi relativi alle virgolette o ai tag HTML poiché Base64 contiene solo caratteri "sicuri" da inserire in una stringa tra virgolette.

La soluzione che propongo: lima

EJS:

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

che renderà in qualcosa di simile (per esempio qui myVar = null):

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

NodeJS lato server:

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

lato client JS (si tratta di un'implementazione di decodifica Base64 che funziona con Unicode, è possibile utilizzare un altro, se si preferisce, ma fate attenzione se supporta Unicode):

var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/=",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}}