How to use readFileSync inside nodeJs vm

I am experimenting with nodeJs vm. This code works:

server.js

var fs = require('fs'); var vm = require('vm'); var app = fs.readFileSync(__dirname + '/' + 'app.js'); vm.runInThisContext(app); var http = require('http'); var server = http.createServer(onRequest); server.listen(8080, '127.0.0.1'); 

app.js

  function onRequest(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end('Hello Node.js\n'); } 

Now, if I change app.js in

  function onRequest(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(fs.readFileSync(__dirname + '/index.html')); } 

It doesn’t work anymore: the browser will print “This web page is unavailable”

How to make it work, perhaps by somehow binding fs.readFileSync to the local onRequest context?

+6
source share
3 answers

Quote from docs :

Code execution does not have access to the local area, but has access to the current global object.

So, the variable __dirname and module fs undefined in this context.

To solve the problem, use the global object:

server.js

 var fs = require('fs'); var vm = require('vm'); global.fs = fs; global.__dirname = __dirname; var app = fs.readFileSync(__dirname + '/' + 'app.js'); vm.runInThisContext(app); var http = require('http'); var server = http.createServer(onRequest); server.listen(8080, '127.0.0.1'); 

app.js

 function onRequest(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(global.fs.readFileSync(global.__dirname + '/index.html')); } 
+1
source

While the answer posted by JohnKiller is technically correct, I would like to point out a solution that uses vm.runInContext and is more reliable in my opinion.

 // app.js var fs = require('fs'); module.exports = function onRequest(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(fs.readFileSync(__dirname + '/index.html')); } // server.js var appFile = __dirname + '/' + 'app.js'; var app = fs.readFileSync(appFile); var context = vm.createContext({ __filename: appFile, __dirname: __dirname, require: require, module: { exports: {} } }); context.exports = context.module.exports; vm.runInContext(app, context, { filename: appFile }); var onRequest = context.module.exports; var http = require('http'); var server = http.createServer(onRequest); server.listen(8080, '127.0.0.1'); 

I see the following main advantages:

1) The global context is not polluted by additional variables used only by the downloaded script file.

2) The code downloaded from the external file is isolated, it cannot directly change the variables of the calling area of ​​the caller. It is very clear which variables are available for the external file.

3) The code in the external file is encapsulated itself and does not depend on any external modules provided in the context. In fact, this is a regular Node.js file that can be downloaded directly via require('./app.js')

+2
source

wtf why?

 var app = fs.readFileSync(__dirname + '/' + 'app.js'); vm.runInThisContext(app); 

just do:

 require('./app.js') 

So, the whole application is as follows:

server.js

 var http = require('http'); // use './' for relative paths var app = require('./app.js'); // load app.js var server = http.createServer(app); server.listen(8080, '127.0.0.1'); 

app.js

 // app.js has to load `fs` for itself var fs = require('fs'); module.exports = function app(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(global.fs.readFileSync('./index.html')); } 

Done

But if for some reason you REALLY want to read, compile and run app.js using vm instead of the plain old require

server.js

 var http = require('http'); // use './' for relative paths var app = vm.runInThisContext('./app.js'); // load app.js var server = http.createServer(app); server.listen(8080, '127.0.0.1'); 

app.js

 // app.js _still_ has to load `fs` for itself var fs = require('fs'); // last value is returned function app(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(global.fs.readFileSync('./index.html')); } 
+1
source

Source: https://habr.com/ru/post/984514/


All Articles