node.js front end web server - node.js

I have seen lots of posts where people are recommending nginx or something similar as the front end web server for node.js.
Since node has the ability to create a web server, such as:
var http = require('http');
var static = require('node-static');
var file = new static.Server();
var url = require('url');
var index = require('./serverJS/index.js');
var login = require('./serverJS/login.js');
var admin_index = require('./serverJS/admin_index.js');
var admin_login = require('./serverJS/admin_login.js');
http.createServer(function (req, res) {
if (url.parse(req.url).pathname == '/index') {
index.serve(req, res);
} else if (url.parse(req.url).pathname == '/login') {
login.serve(req, res);
} else if (url.parse(req.url).pathname == '/admin/index') {
admin_index.serve(req, res);
} else if (url.parse(req.url).pathname == '/admin/login') {
admin_login.serve(req, res);
} else {
file.serve(req, res);
}
}).listen(9000 , '127.0.0.1' );
Q: In what case scenario would you need another web server in adition to node's?

A front-end Nginx would be more efficient at serving static assets.
A front-end Nginx would also be useful if you wanted to run multiple backend servers, like Node.js combined with Apache/PHP where Node.js serves some routes and Apache/PHP serves other routes.

Related

Using .createServer to make a public website

So I have a file I want to host from my computer, and I want to be able to listen at the port for various reasons. I'm using
const port = [number]
http.createServer((req, res) => {
let responseCode = 404;
let content = '404 Error';
const urlObj = url.parse(req.url, true);
if (urlObj.query.code) {
const accessCode = urlObj.query.code;
}
if (urlObj.pathname === '/') {
responseCode = 200;
content = fs.readFileSync('./index.html');
}
res.writeHead(responseCode, {
'content-type': 'text/html;charset=utf-8',
});
res.write(content);
res.end();
})
.listen(port);
and all that good stuff makes it where I can have a local file, http://localhost:[number]. However, I'm not exactly sure how I can use this same method for hosting on an online website, one in which I upload my code to the website then have the website started from my computer (using the create server). Does anyone know how to basically create a server that's not private/local, but instead is public (and yes I can use a web host).
I recommend using the express framework as it greatly simplifies serving static files. It would be as simple as the following:
const express = require('express');
const app = express();
const port = 3000;
app.use(express.static(__dirname + '/public'));
app.listen(port , () => {
console.log(`Server is running at port ${port}`);
});
With above code all that's left to do is to create folder called public in your app directory where you place your html/css/js files.

In Node.js is it possible to create a virtual folder if so how

In Node.js is it possible to create a virtual folder if so how?
Some context for needing a virtual folder:
Have a project in Node.js that is a middleware is listinning to port 400 for example so can make request to my endpoints as follow http://{IP}:400/?p={%22getWebhooks%22:true}. The port 400 is open to make external requests.
In the same server there is another middleware that is .NET/C# that is using port 80 and it only works inside the server (its blocked from the outside)
This Project serves to integrates images among other data, those images are saved in folder under that .NET project where in the Node.js need's to have access to those images in the folder (to avoid having to ask for another port to be open to the outside/ public IP)
The Node.js project is in C:\nodeProject
http://{IP}:400/?p={%22getWebhooks%22:true}
The Images folder is in C:\inetpub\wwwroot\{.netProject}\back_office\resources
to avoid needing another open port for The IIS for example port 200 to serve the images
http://{IP}:200/resources/images.jpg
wanted to serve the images using Node.js
http://{IP}:400/resources/images.jpg
Not using express.js using the http module
var server = http.createServer(function (req, res) {
Don't know if node-static package can be use for this use-case...
Thanks for any information that points me in the right direction.
As #Molda refered by using the package node-static solved my probleam but had to use inside my app as in the code bellow where query === null is condition to see if the request doesn't have paramter's then its a image to be serve other wise it a normal request to endpoint of my Node.js app middleware.
var staticNode = require('node-static');
var fileServer = new staticNode.Server('C:/inetpub/wwwroot/example/back_office/resources/');
var server = http.createServer(function (req, res) {
let body = []
req.on('error', (err) => {
console.error(err);
}).on('data', chunk => {
body.push(chunk);
}).on('end', () => {
let bodyResponse;
if (body.length > 0) {
bodyResponse = JSON.parse(body);
//console.log(body);
console.log(bodyResponse);
}
//var page = url.parse(req.url).pathname;
var query = url.parse(req.url).query
var params = querystring.parse(query);
if(query === null){
fileServer.serve(req, res);
}else{
if ('p' in params && isJSON(params['p'])) {
var p = JSON.parse(params['p']);
switch (Object.keys(p)[0]) {
...
}
} else {
res.write(JSON.stringify({
"errorMessage": "invalid request format"
}));
res.end();
}
}
}).resume();
});

Nodejs - BrowserSync running on express server

I want to pull a URL from the DB and use it as the proxied URL. However the setup I've come up with initializes a new BrowserSync server for each URL, using incrementing port numbers.
Is there a way to accomplish this without initializing a new BrowserSync server every time?
Or should I be using another approach?
var bs = require("browser-sync");
var express = require("express");
var router = express.Router();
var app = express();
router.get("/", function(req, res){
var proxyUrl = getUrl() //get url from db (www.example.com)
bs.create("bs1").init({
notify: false,
open: false,
ui: false,
port: 10000,
proxy: proxyUrl
});
res.send();
});
app.use(router);
app.listen(8080, function(){
console.log('listening on *:8080');
});
The above is fine(ish) but is it good practice to be initializing a new server for every URL (potentially thousands)?
And is it safe to be exposing a new port number to every user of the system? (Can I mask this with a subdomain?)
Update
My end goal is to use a unique subdomain to refer to each proxy url.
For example:
sub1.mysite.com proxies www.example.com,
sub2.mysite.com proxies www.example2.com
Browser-sync will not work as the proxy is tie to server setup.
I use following packages:
express
express-http-proxy
vhost (express vhost)
const port = 8080;
var app = require('express')();
var proxy = require('express-http-proxy');
var url = require('url');
var vhost = require('vhost');
app.listen(port);
/* Assuming getUrl() will return an array of sites */
// var sites = getUrl();
// DO NOT put '/' at the end of site
var sites = [
'http://www.bing.com',
'http://samanthagooden.com',
'http://www.courtleigh.com'
];
var i = 0;
sites.forEach(site => {
i++;
var subDomain = 'sub' + i + '.mysite.com';
app.use(vhost(subDomain, proxy(site, {
forwardPath: (req, res) => url.parse(req.url).path,
intercept: (rsp, data, req, res, callback) => {
if (res._headers['content-type']) {
var contentType = res._headers['content-type'];
if (
contentType.indexOf('text') !== -1 ||
contentType.indexOf('javascript') !== -1
) {
// Replace link if content-type = text or javascript
var reg = new RegExp(site, 'g');
res.send(data.toString().replace(reg, ''));
} else {
res.send(data);
}
} else {
res.send(data);
}
}
})));
console.log(subDomain + ':' + port + ' proxy: ' + site);
});
The above example will create following proxies:
sub1.mysite.com:8080 proxy: www.bing.com
sub2.mysite.com:8080 proxy: www.example.com
Maybe I'm misunderstanding what you are trying to do, but Browsersync and express seems a bit overkill in this case, why not just use node-http-proxy with the native http module?
var http = require('http')
var httpProxy = require('http-proxy')
var options = ...
var proxy = httpProxy.createProxyServer(options)
var server = http.createServer(function (req, res) {
var proxyUrl = getUrl()
proxy.web(req, res, { target: proxyUrl })
})
server.listen(8080, function () {
console.log('listening on *:8080')
})
As per me If you want SAAS service using proxy is not the good idea to go is what am thinking.. if you are going with proxy for each client will create process with new port... My Solution is to create node server with listen localhost and map *.domain.com to the server..
If you are using individual database for each client :-
in node logic get cname from request host and use that reference to connect database.
Final Controller code would be..
var express = require('express');
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
/* GET home page. */
router.get('/', function(req, res, next) {
var client = req.subdomains[0];
console.log(client);
MongoClient.connect('mongodb://localhost:27017/'+client, function(err, db) {
if (err) {
throw err;
}
db.collection('app1').find().toArray(function(err, result) {
if (err) {
throw err;
}
console.log('data');
console.log(result);
});
});
res.render('index', { title: 'Express' });
});
module.exports = router;
~
~
In future if you get more clients you can implement node cluster or standard Ubuntu cluster using webservice

How to redirect requests / proxy based on User-Agent (mobile and desktop) using Grunt or Node server?

I'm using Grunt and its proxying library grunt-connect-proxy. I have two servers setup for the desktop and mobile versions of my site (both of which have separate assets and such, hence the separation). Both sites are hosted on 0.0.0.0 but on different ports (9000 and 10000).
How can I proxy requests to the two different servers based on the User-Agent header (which will tell me if it is a mobile or desktop user)? Is there another solution in NodeJS I could use?
I ended up writing a NodeJS server which used the http-proxy and mobile-detect packages to proxy requests.
var servers = {
desktopClientFrontend: 'http://0.0.0.0:10000',
mobileClientFrontend: 'http://0.0.0.0:9000',
railsApiBackend: 'http://0.0.0.0:11000'
};
var http = require('http'),
url = require('url'),
httpProxy = require('http-proxy'),
MobileDetect = require('mobile-detect');
var proxy = httpProxy.createProxyServer({});
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
});
var server = http.createServer(function(req, res) {
if(url.parse(req.url).pathname.match(/^\/api\//)) {
proxy.web(req, res, { target: servers.railsApiBackend });
} else {
var mobileDetect = new MobileDetect(req.headers['user-agent']);
if(mobileDetect.mobile()) {
proxy.web(req, res, { target: servers.mobileClientFrontend });
} else {
proxy.web(req, res, { target: servers.desktopClientFrontend });
}
}
});
server.listen(80);

host multiple pages on nodejs

So I have my app at http://localhost:8080/
How can I have http://localhost:8080/subpage ? Because it seems like any page that hits :8080 pulls the server.js
thanks!
** edit - here's what worked for me (thanks to stewe's answer) **
var app = require('http').createServer(createServer);
var fs = require('fs');
var url = require('url');
function createServer(req, res) {
var path = url.parse(req.url).pathname;
var fsCallback = function(error, data) {
if(error) throw error;
res.writeHead(200);
res.write(data);
res.end();
}
switch(path) {
case '/subpage':
doc = fs.readFile(__dirname + '/subpage.html', fsCallback);
break;
default:
doc = fs.readFile(__dirname + '/index.html', fsCallback);
break;
}
}
app.listen(8080);
Here is a start:
var http=require('http');
var url=require('url');
var server=http.createServer(function(req,res){
var pathname=url.parse(req.url).pathname;
switch(pathname){
case '/subpage':
res.end('subpage');
break;
default:
res.end('default');
break;
}
}).listen(8080);
I hit the same problem as you did, and I think what we were both looking for is basically a routing engine for node.js. Basically, okay fine I get the hello-world example for nodejs, but how do I build something that responds to different requests?
For future users who land on this page via google, you must look at Express.js and this excellent guide and intro into express, Understanding Express.js. These two will solve the problem

Resources