nodejs app works locally but not when deployed - node.js

I'm using iisnode to host a node app. I'm having trouble actually deploying it under my domain name. Here's the main file with two different starting points. The un-commented code is just a simple server that works correctly when accessed via my domain (so iisnode is mapping and handling the node app correctly). The commented code is the entry point for the express app I am working on, and this works when I view from a local host, but when attempting to access via my domain I receive a 'cannot GET application.js' error.
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, world!');
}).listen(process.env.PORT);
//require('./app/init');
//var server = require('./app/server');
//module.exports = server.start(process.env.NODE_ENV);
Here is my server.js file. I think its a routing issue, I've substitued a console.log function for the indexRoute function, and it never fires. But I still don't understand why this works correctly accessing via localhost but not under my domain.
var express = require('express');
var routes = require('./routes');
var app = express();
function createApplication(environment) {
app.get('/', routes.indexRoute);
app.listen(process.env.PORT);
return app;
}
module.exports.start = createApplication;
I can message a git link for full app if anyone is interested.

Try specifying that you want to listen from all IP addresses, not just localhost by adding '0.0.0.0' as a parameter to listen. Also add a callback to see what happened.
app.listen(process.env.PORT, '0.0.0.0', function(err) {
console.log("Started listening on %s", app.url);
});

Related

Can't get WebSocket Server running on a subdomain (Plesk, Linux, NodeJs, Express)

I’ve developed myself a little WebSocket Server which works perfectly (local - on my IDE). The problem is that I want to host it on my server managed with Plesk under a specific subdomain that I've created: ws.my-url.de.
This is my server.js file:
const {logInfo} = require('./logger');
const WebSocketServer = require('ws').Server;
const express = require('express');
const uuid = require('node-uuid');
const app = express();
const wss = new WebSocketServer({
server: app.listen(process.env.PORT || 8888)
});
logInfo('WebSocket Server successfully started');
wss.on('connection', ws => {
ws.id = uuid.v4();
logInfo(`Client connected: ${ws.id}`);
ws.on('message', function () {
logInfo(`New message from client: ${ws.id}`);
});
ws.on('close', function () {
logInfo(`Client: ${ws.id} closed connection`);
});
});
wss.on('close', function () {
logInfo('WebSocket Server stopped');
});
app.post('/', function (req, res) {
logInfo(req);
});
I've also implemented a logger that logs out to a file which works also great (directly on start e.g. my startup message) but inside the logs folder on my server is a yawning emptiness.
I really can't get my WebSocket Server running on my server. To leave no stone unturned, I've disabled the proxy mode from nginx but after trying to connect to wss://ws.my-url.de I'm getting this error:
WebSocket connection to 'wss://ws.my-url.de/' failed: Error during WebSocket handshake: Unexpected response code: 500
So I can say that my server is not starting. To be really sure (and to exclude other things), I've wrote a little http server found in the internet and this ran straight out of the box after pressing the Restart App button (I saw the response in the browser window):
const http = require('http');
http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('App is running…');
}).listen(process.env.PORT);
This is my configuration by the way:
When I open the URL after trying to start my WebSocket Server, I'm getting this error:
So what I'm doing wrong here? I don't want a page I can open, I just want to get this running as a little service which is accessible over my subdomain. I'm very overwhelmed with this and thankful for every person who can help me.

Simple subdomain with Express

I am trying to use Express as my server in MEAN stack on AWS. However I've ran into a issue trying to setup subdomains. I have my main domain name domain.com and id like to have app.domain.com.. However I've tried everything I've found online to write the functionality into the server.js file and nothing works. How can I easily accomplish this to make the second function instead of loading on Port 8000 load up at my app.domain.com sub domain? Thanks in advance!
var express = require('express');
// Main Website
var web = express();
web.get('/', function (req, res){
res.sendFile('/web/index.html', { root: '.' })
});
var port = 9000;
web.listen(port);
console.log('Web Listening on port', port);
//Main Application
var app = express();
app.get('/', function (req, res){
res.sendFile('/app/index.html', { root: '.' })
});
var port = 8000;
app.listen(port);
console.log('Web Listening on port', port);
Update:
I tried using Vhost here but it loads the same thing for both the main domain and the sub domain and so it does not work. here is the code I used:
var express = require('express');
var connect = require('connect');
var http = require('http');
var vhost = require('vhost');
// Main Website
var web = express();
web.get('/', function (req, res){
res.sendFile('/web/index.html', { root: '.' })
});
var port = 9000;
web.listen(port);
console.log('Web Listening on port', port);
//Main Application
var app = connect()
app.use(vhost('app.domain.com', function (req, res) {
res.sendFile('/app/index.html', { root: '.' })
httpServer.emit('request', req, res)
}))
app.listen(8000)
I don't really need these to be on separate ports that was just something I was trying originally. But either way does not work still..
There's no need for any thing outside of node.js serving on one port. It's just a matter of routing based on the http header.
var express = require('express');
var http = require('http');
var vhost = require('vhost');
// Main Website
var webapp = express();
webapp.get('/', function (req, res){
res.sendFile('/web/index.html', { root: '.' });
});
//Main Application
var mainapp = express();
mainapp.use(function (req, res) {
res.sendFile('/app/index.html', { root: '.' });
}));
//Virtual Routing Application
var app = express();
app.use(vhost('app.domain.com', webapp));
app.use(vhost('domain.com', mainapp));
app.use(vhost('www.domain.com', mainapp));
app.listen(9000);
Since you're using AWS, you can use Application Load Balancer to achieve your goals.
Setup an ALB, and point both domains to the ALB CNAME.
Then you will need to create 2 target groups, one for app.domain.com and another one for domain.com.
Target Group: App
protocol: HTTP
port: 8000
Target Group: Web
protocol: HTTP
port: 9000
Attach your EC2 instance to both target groups
Target group > Targets > Edit > Add to registered
Finally you will have to add an HTTP listener to your ALB, and setup the rules to forward each domain to its target group.
After the rules are set, when you enter to app.domain.com the ALB will forward the request to your express app listening on port 8000, and when browsing domain.com the one listening on port 9000 will be used.
If you are using Route53 I recommend you to use Records Set to redirect both domain and subdomain to the same ec2 instance via the ip address then you can use ngix like the comments say in this post enter link description here
Using the load balancer (ALB) generates montly the minimum cost of 21.96USD but using Route53 it is minimum of 1USD or less.
If you dont want to use a proxy like nginx you can have s3 website hosting with a low cost, arround 6USD and the route 53 routing by 1USD minimum per month and if you have REST API services you can call from front end to your instance depending the site accessed with no problems.
Regards,

AWS EC2 NodeJS doesn't respond

I've got an AWS EC2 MEAN instance up and running (partially). The app is a RESTful JSON service and as far as I can tell is up and running as expected:
var app = require('./app');
var port = process.env.PORT || 3000;
var server = app.listen(port, function() {
console.log('Express server listening on port ' + port);
});
console output:
node server.js
Express server listening on port 3000
Db.prototype.authenticate method will no longer be available in the
next major release 3.x as MongoDB 3.6 will only allow auth against
users in the admin db and will no longer allow multiple credentials on
a socket. Please authenticate using MongoClient.connect with auth
credentials.
I've also added the Inbound Security Group for port 3000
testing the API out in the browser is where I run into problems... If I attempt to GET a list of objects using http://ec2-XX-XX-XX-XX.com:3000/belts the call eventually times out. However when I try a GET for a single object using http://ec2-XX-XX-XX-XX.com:3000/belts/some_id_here I get a valid 200 response with the expected object.
Of course everything works as expected locally. What am I missing?
Thanks in advance
//edit with requested code formatted :)
//app.js
var express = require('express');
var app = express();
var BeltController = require('./controller/BeltController');
app.use('/belts', BeltController);
//Belt Controller
router.get('/', function (req, res) {
Belt.find({}, function (err, belts) {
if (err) {
return res.status(500).send("There was a problem finding the Belt. " + err);
}
res.status(200).send(belts);
});
});

Express POST returns 404 on Apache

There is a React app that has express requesting api/login information from Mongodb and checking the password input against it, otherwise it doesn't allow you to access the website.
Locally everything works great. When we moved all the build files to the apache server the console returns POST https://websitepath.com/api/login 404 (Not Found)
Any idea of what could be a problem and why it works locally but doesn't work on apache? Node is installed and Express is running there successfully on port 4000.
Here is the code for index.js
var express = require('express');
var bodyParser= require('body-parser')
var MongoClient = require('mongodb').MongoClient
var sha1 = require('sha1');
var db;
const PORT = 4000;
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use('/api/login', function (req, res) {
if (!req.body.password) return res.status(400).send('bad_request!')
db.collection('user').find().toArray(function(err, results) {
if (err) return res.status(500).send('something_wrong!');
var checker = false;
results.forEach(function (entry) {
if (entry.password === sha1(req.body.password)) checker = true;
})
if (checker) {
res.send('success')
} else {
return res.status(403).send('Unfortunately password is incorrect. Please try again.');
}
})
})
MongoClient.connect('mongodb://localhost:27017/test', (err, database) => {
if (err) return console.log(err)
db = database
app.listen(PORT, function() {
console.log('Express server is up on port ' + PORT);
});
})
Here is the code for the AuthService.js
import axios from 'axios';
import qs from 'qs';
const AuthService = {
isLogged: false,
login(data, cb) {
axios.post('/api/login', qs.stringify(data)).then(
(res) => {
this.isLogged = true;
cb(null, res);
}
).catch((error) => {
console.error('error occured', error);
cb(error.response.data);
})
},
}
export default AuthService;
Your question doesn't mention proxying the node.js application, so I'm guessing that's where the problem is - specifically, the node application is not being proxied.
In short, what you appear to be trying to do is something like this:
Apache is listening on port 443 (the HTTPS port) and serving web pages at various paths (presumably, everything except paths starting with /api).
You want the web server to also serve the paths used by your node.js API (eg. /api/login and others) on port 443.
But two distinct applications (Apache and your node.js app) cannot both listen on port 443 - Apache is binding it and serving its own pages. If you try to change the port on your node.js application, it will fail to start and give you an error indicating that port 443 is already bound by another application.
There is a simple test for this: navigate to http://websitepath.com:4000/api/login. If you can see your API login page (ie. the node.js application is listening on port 4000), that means the problem is NOT with your node application, it's with Apache's proxy configuration.
The solution to this is setting up Apache as a proxy. This will allow Apache to serve its own pages and forward the request to another service based on the path. So you could certainly set it up so paths that start with /api/... are forwarded to http://localhost:4000/api/... and any other paths are served by Apache directly.
Setting up a proxy is not terribly difficult, but it depends a lot on your specific circumstances, so I'm not going to attempt to explain all the ins & outs. I'd recommend starting with the mod_proxy documentation. There are also about a million tutorials out there; Digital Ocean's documentation is good - I've used it in the past.

Host multiple websites using Node.js Express

I am having problems configuring two different Node.js applications with different domains. Have two directories
"/abc/" -> express-admin setup (backend) -> admin.abc.com
and
"/xyz/" -> express setup (frontend) -> abc.com
I need admin.abc.com to point to express-admin setup and abc.com to express setup. I have vhost installed and both the site listens to port 80.
Have added
app.use(vhost('abc.com', app)); // xyz/app.js file
app.use(vhost('admin.abc.com', app)); // abc/app.js file
My problems:
forever is installed, whenever i start both the apps, the second one is always stopped. I tried using different port for both apps but still having the same error. Individually they run without problems.
I think my setup is too complicated for domain forwarding. Any better suggestions? May be I have a master app.js file which I can use to route the domains to their respective apps without using the app.js of each applications.
I am not sure how you are using the vhost. First of all with vhost approach, you need to run only one express app. Not two. Here is an example.
var express = require('express');
var vhost = require('vhost');
/*
edit /etc/hosts:
127.0.0.1 api.mydomain.local
127.0.0.1 admin.mydomain.local
*/
// require your first app here
var app1 = require("./app1");
// require your second app here
var app2 = require("./app2");
// redirect.use(function(req, res){
// if (!module.parent) console.log(req.vhost);
// res.redirect('http://example.com:3000/' + req.vhost[0]);
// });
// Vhost app
var appWithVhost = module.exports = express();
appWithVhost.use(vhost('api.mydomain.local', app1)); // Serves first app
appWithVhost.use(vhost('admin.mydomain.local', app2)); // Serves second app
/* istanbul ignore next */
if (!module.parent) {
appWithVhost.listen(8000);
console.log('Express started on port 8000');
}
You just need to run the main express app with vhost enabled using forever.
You're hosting the applications on the same port, using the same network interface. So when the second app starts, it will always find the port in use. If you want to use multiple applications on the same port, they each need to have their own network interface. When using vhost, you would still need to listen on a different port for each app. See this example for details. If you would like your apps to be completely independent, you're better off using node-http-proxy. This allows you to host a proxy on port 80 which forwards requests to express apps listening on different ports. If one of these apps crashes, it will not crash the other app, unlike the vhosts approach. This post gives an example of the implementation using node-http-proxy.
Thanks #veggiesaurus for pointing up to node-http-proxy. Apologies for posting late.
Here is how I solved my problem using node-http-proxy
Folder Structure:
www/
server.js
abc/ [express setup]
app.js
xyz/ [express-admin setup]
node_modules/express-admin/app.js
"abc" and "xyz" have there own setup and running on port x.x.x.x:3001 and x.x.x.y:3002
I installed node-http-proxy and added server.js file with following codes. Referred this link
var http = require('http');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxy();
var options = {
'abc.com': 'http://x.x.x.x:3001',
'xyz.com': 'http://x.x.x.y:3002'
}
http.createServer(function(req, res) {
proxy.web(req, res, {
target: options[req.headers.host]
});
}).listen(80);
Finally, used forever to run all 3 apps setup to run forever in port 3001, 3002 and 80.
const express = require("express");
const app = express();
const fs = require('fs');
app.use((req, res, next) => {
let reqDomain = req.get("host");
if (reqDomain.indexOf(":") > -1) {
reqDomain = reqDomain.split(":")[0];
}
if(reqDomain.endsWith(".local")) {
reqDomain = reqDomain.substring(0, reqDomain.length - 6);
}
const domainPath = "public/" + reqDomain;
let filePath = domainPath + req.originalUrl;
filePath = fs.lstatSync(filePath).isDirectory() ? filePath + "/index.html" : filePath;
console.log(__dirname + "/" + filePath);
res.sendFile(filePath, { root: __dirname });
});
const port = process.env.PORT || 80;
app.listen(port, () => console.log("Server Started on Port " + port));
Inside public directory put you folder like 'my-first-website.com', 'my-second-website.com'
To test locally add following in /etc/hosts
127.0.0.1 my-first-website.com.local
127.0.0.1 my-second-website.com.local

Resources