NodeJS .fork() using threads - javascript

I'm needing to run Node servers for the development of several independent projects on a single box.
With Nginx in front routing based on virtual hosts, running 15+ node instances working separately isn't normally much of a problem. The catch is that just starting node that many times eats all my RAM with the overhead of just the internal libraries.
So does there exist a solution for this, allowing me to run several largely-independent Node servers while sharing the core libraries? Here are what I've considered:
Threads instead of processes—there would exist a master control process that would be able to create a new thread for each instance. I know Node is built to not require threads, but is there a way to utilize them in order to save memory?
Some library or addition to Node allowing me to do the above.
Shared core memory between processes—is this a possibility for Node?
Just require ()ing in each server onto the same Node instance—I can't think how killing or reloading those servers could work. Is there a way to unrequire and restart an external module? This method could be ideal by allowing other libraries (Socket.IO for example) to be shared.
Anyway, this is probably an edge case, so I'm not surprised that a solution isn't obvious.
Does anyone know of a way to implement this?

The existing thread libraries limit your access to I/O pretty severely and are intended for you to run your own CPU-bound Javascript code, not serve out data. Shared core is certainly possible, but also a bit of a pain. I think your last option is the most viable. You can put together a virtualization system for node pretty easily.
Here are a couple standalone Express apps.
app-one.js:
var app = require('express')();
app.get('/', function (req, res) {
res.send('This is app one.');
});
app.listen(3000);
app-two.js:
var app = require('express')();
app.get('/', function (req, res) {
res.send('This is app two.');
});
app.listen(3001);
Change those by replacing the listen lines with assignments to the module:
app-one-virtual.js:
var app = require('express')();
app.get('/', function (req, res) {
res.send('This is app one.');
});
module.exports = app;
app-two-virtual.js:
var app = require('express')();
app.get('/', function (req, res) {
res.send('This is app two.');
});
module.exports = app;
Then write a master app that requires each of those and delegates requests to them based on the incoming host header:
app-master.js:
var http = require('http');
var appOne = require('./app-one-virtual');
var appTwo = require('./app-two-virtual');
http.createServer(function (req, res) {
if (req.headers.host === 'one.example.com:3000') {
return appOne(req, res)
}
if (req.headers.host === 'two.example.com:3000') {
return appTwo(req, res)
}
res.writeHead(404)
res.end('Site not found.')
}).listen(3000);
Now just node app-master.js and you're set. Repeat for as many servers as you like.

Related

Is Express.js platform-independent?

I'm just starting out with Express.js. In the official getting started guide, they showed the following basic code:
var express = require('express')
var app = express()
// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
res.send('hello world')
})
The first parameter to app.get() is a forward-slash indicating the root directory. But the slash is a backward-slash in windows systems. Does express deal with these differences automatically, or do we need to write extra code for it? When I was using the http module, I did have to consider and correct for these differences. Thanks for the help!
app.get('/', ...) declares a handler for when an HTTP GET request is made to the URL path /. E.g. http://localhost:8080/. It has nothing to do with file paths on the server’s file system. If you use any functions that do take a file path, you may have to account for the differences between Windows and *NIX, that depends on the function.

Express performance requiring modules

Having a question regarding the performance of a NodeJS application.
When I have the following express app in NodeJS:
const app = require('express')();
const about = require('./about');
app.use('/about', about);
app.listen(3000, () => console.log('Example app listening on port 3000!'));
My current understanding is that only when the server is started up it does need to require() these files using commonJS modules.
Question:
Does the express application has to execute the require() statements with every request to the server or is this only necessary when starting the server?
Any extra information about how express works under the hood would be nice.
No, those require are only run once when you start the app. It would be different if you include those in the router functions.
app.use('/about', (req, res) => {
const some = require('some');
});
Still in this scenario, modules require are cached so it's not such a big deal.

Socket.io - Don't allow client to view files with the main.js file

I am currently working on a project which uses socket.io with NodeJS to control something else. This is my code so far:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require('fs');
var contents = fs.readFileSync("data.json");
var remoteLayout = JSON.parse(contents);
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/edit', function(req, res) {
res.sendFile(__dirname + '/edit.html');
});
app.use(express.static(__dirname));
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(8080, function() {
console.log('listening on *:8080');
});
It is my code shortened to the parts which are relevant.
So my question is, when I run this code in node, and I open the page [myIPAddress]:8080 it opens up index.html like it should and at the top of Chrome, it says [myIPAddress]:8080. Now if I to the bar which shows the page's URL at the top, and change that to [myIPAddress]:8080/handler.js it opens a page with my js script printed out on it. How do I make it so that the person cannot go to that [myIPAddress]:8080/handler.js page?
I'm not sure if it matters, but the folder with the main.js file has also index.html, edit.html, and handler.js.
The problem is this:
app.use(express.static(__dirname));
When you do that, you've exposed all files in the __dirname directory for anyone to see including your server files that are located in that directory. Instead, you should move your static files that you intend for the public to have access to to some other directory and then use:
app.use(express.static(someOtherPath));
This will keep your server files in __dirname private and expose only the files you intend to be public that you have located in someOtherPath.
If handler.js is actually intended for use in your web pages and thus must be made available to the browser, then you cannot prevent anyone from looking at it. If your webpage needs to use it, then the browser must be able to download it and if the browser must be able to download it, then you cannot prevent a person from seeing it. You can do all sorts of things like obscure it to make it less intelligible to a person, but to any determined hacker, the logic will still all be there and you can't hide any Javascript intended to run in a browser.
Logic that you want to protect MUST be only on your server, perhaps usable via Ajax calls. You can't keep code secret that must run in a browser.

Filesystem Module in Parse Web Server

I am currently attempting to use Parse Web Hosting to setup a website for my iOS application. I am attempting to show a PDF file in the web browser located within my website directory. I am using express and heres whats going on so far
var express = require('express');
var app = express();
var fs = require('fs');
// Global app configuration section
app.set('views', 'cloud/views'); // Specify the folder to find templates
app.set('view engine', 'ejs'); // Set the template engine
app.use(express.bodyParser()); // Middleware for reading request body
app.get('/terms', function(request, response){
fs.readFile("/public/terms_conditions_hotspot.pdf", function (err,data){
response.contentType("application/pdf");
response.render(data);
});
});
app.listen();
So when I navigate to mysite.parseapp.com/terms, I get a 500 error.
But to make sure everything is setup correctly, I used Parse's boilerplate code to render a hello message when you navigate to mysite.parseapp.com/hello.
app.get('/hello', function(request, response) {
response.render('hello', { message: 'Congrats, you just set up your app!' });
});
This seems to work fine. Anyone know what the issue is?
My goal is migrating my Django Web app to using Parse Web Hosting instead mainly because Parse supports SSL and supplies free certs, which makes building this application cheaper (free). Although, my Django Web App's purpose is to deal with Stripe Connect redirects and used oAuth2, which may be problematic with the migration, seeing as Parse may not support certain modules or whatever. I just feel Parse is very limited with their services but I am anxious to see what I can do with it.
EDIT
So I ran console.log(error) and it returned:
Object [object Object] has no method 'readFile'
readFile is definitely a method that fs ('filesystem') contains. So maybe the module 'fs' in Parse isn't up to date or refers to a different module?
What the deuce?
Parse doesn't appear to use NodeJS (fs is a Node module) even though they offer Express.
See: https://www.parse.com/questions/loading-nodejs-packages-to-cloud-code

Okay to add a route to Node.js Express while listening?

Obviously the typical example of adding routes to express follows something like the following:
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
Clearly, in most cases you know the get route exists before the server begins listening. But what if you want to dynamically create new routes once the server is listening? In other words, I want to do something like the following:
var express = require('express');
var app = express();
app.listen(3000, function () {
app.get('/', function(req, res){
res.send('hello world');
});
});
In practice the callback of the route would obviously be pulled dynamically from some remote source. I've tested the above code and everything appears to function properly, however, I was hoping to get confirmation that there wouldn't be any unintended side-effects of creating routes after app.listen is called before I move forward with this pattern.
Note: To clarify, I don't know what the routes will be when I write the main server.js file that will be creating the express server (hence why I can't create the routes before listen is called). The list of routes (and their respective handlers/callback functions) will be pulled from a database while the server is starting up/running.
According to TJ (author of Express), it’s okay to add routes at runtime.
The main gotcha is going to be that routes are evaluated in the order they were added, so routes added at runtime will have a lower precedence than routes added earlier. This may or may not matter, depending on your API design.

Categories