Use socket.io with HTTPS instead of HTTP - sockets

I am using self-signed certificated to encrypt traffic data.
My .crt and .key files are located at /etc/nginx/ssl/
(some_file.key and some_file.crt)
I was using socket.io over http but tried to get it over to https. Here is my actual code:
var formidable = require('formidable');
var express = require('express');
var fs = require('fs');
var privateKey = fs.readFileSync('../etc/nginx/ssl/some_file.key').toString();
var certificate = fs.readFileSync('../etc/nginx/ssl/some_file.crt').toString();
//how can I exclude this? (I have no intermediate, should I?)
var ca = fs.readFileSync('../intermediate.crt').toString();
var app = express.createServer({key:privateKey,cert:certificate,ca:ca });
var io = require('socket.io');
app.listen(3000, function(){
//wait on 3000
});
app.post('/posts', function(req, res){
//server communication
});
io.on('connection', function(socket){
//wait on connections
});
Client-side:
var socket = io(url + ":3000", { "secure": true, 'connect timeout': 5000 });
Is this the correct way to do it? I based my https code on examples, so I'm doubting on whether this is well enough (I know it isn't, but should be close). When I run the code, I also get an error no such file or directory '../etc/nginx/ssl/some_file.key'...

I use it this way, although this is very dependent on express version you are using. This is for version 3.4
var express = require('express')
, app = express()
,fs = require('fs')
,events = require('events');
...
var options = {
key: fs.readFileSync('/etc/nginx/ssl/some_file.key'),
cert: fs.readFileSync('/etc/nginx/ssl/some_file.crt')
};
/*
*Configuration
*
*/
var server = require('https').createServer(options, app), io = require("socket.io").listen(server);
var port = 8443;
var ipaddr = '0.0.0.0';
app.configure(function() {
app.set('port', port);
app.set('ipaddr', ipaddr);
app.use(express.bodyParser());
app.use(express.methodOverride());
...
});

Related

router .use() requires a middleware function but got a string

I am using EJS for templating, when I add this
app.use("view engine","ejs")
in my code i get error.
router .use() requires a middleware function but got a string
The rest of the code:
const express = require('express');
const bodyParser = require('body-parser');
const port = 3000;
const app=express();
app.use("view engine","ejs");
app.get('/', function(req, res){
var today = new Date();
var currentDay = today.getDay();
var day ="";
if(currentDay === 6 || currentDay === 0){
day ="weekend";
}else{
day = "weekday";
}
res.render("list",{kindOfDay:day});
});
app.listen(port, function(){
console.log('The server has started');
});
Look at the documentation for using template engines:
app.set('view engine', 'pug')
use is used to add middleware, and a string isn't middleware, hence the error message.
You need to use set to set a setting.

Parse Server - Image files' path returns localhost

I have deployed 2 Ubuntu servers on Azure. First, I have installed the Parse Server and the second, I installed MongoDB. (I have also put a ready db there from my previous server via mongorestore)
Everything works fine! Both Parse Server and MongoDB server. They also communicate well. The thing is, when I run my iOS app, it brings all data correctly, except images. I print the URL of an image and here's what it returned: http://localhost:1337/parse/files/filename.jpeg
If I replace localhost with my server's ip, the image is being fetched nicely!
Here's what I have on my index.js:
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var ParseDashboard = require('parse-dashboard');
var allowInsecureHTTP = true;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGODB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || 'mongodb://IP:27017/db',
cloud: './cloud/main.js',
appId: process.env.APP_ID || 'xxx',
masterKey: process.env.MASTER_KEY || 'xxx', //Add your master key here. Keep it secret!
fileKey: 'xxx',
serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse', // Don't forget to change to https if needed
// Enable email verification
verifyUserEmails: false,
// The public URL of your app.
// This will appear in the link that is used to verify email addresses and reset passwords.
// Set the mount path as it is in serverURL
publicServerURL: 'http://localhost:1337/parse',
});
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
// If you wish you require them, you can set them as options in the initialization above:
// javascriptKey, restAPIKey, dotNetKey, clientKey
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('Make sure to star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// Set up parse dashboard
var config = {
"allowInsecureHTTP": true,
"apps": [
{
"serverURL": "http://localhost:1337/parse",
"appId": "xxx",
"masterKey": "xxx",
"appName": "name",
"production": true
}
],
"users": [
{
"user":"username",
"pass":"pass"
}
]
};
var dashboard = new ParseDashboard(config, config.allowInsecureHTTP);
var dashApp = express();
// make the Parse Dashboard available at /dashboard
dashApp.use('/dashboard', dashboard);
// Parse Server plays nicely with the rest of your web routes
dashApp.get('/', function(req, res) {
res.status(200).send('Parse Dashboard App');
});
var httpServerDash = require('http').createServer(dashApp);
httpServerDash.listen(4040, function() {
console.log('dashboard-server running on port 4040.');
});
One thing I noticed at Parse's documentation, is this: When using files on Parse, you will need to use the publicServerURL option in your Parse Server config. This is the URL that files will be accessed from, so it should be a URL that resolves to your Parse Server. Make sure to include your mount point in this URL.
The thing is that this documentation was written having in mind MongoDB, is on the same server with Parse, which in my case isn't.
Any ideas on what to do?
I had to replace the publicServerURL of parse server's config, from http://localhost:1337/parse to http://publicIP:1337/parse and everything worked out great!
If you want to work with files(images) download them, just use publicServerURL as mentioned #Sotiris Kaniras
I would add that the config.json is in ~/stack/parse/config.json. Also here is the difference between serverURL and publicServerURL
Difference between serverURL and publicServerURL on ParseServer
In my case, I needed to add publicServerURL parameter alongside with serverURL because it hasn't existed yet.
So both parameters(publicServerURL & serverURL) are complement, not mutually exclusive, use them both.

cannot GET / express.js routing

I am at the early stages of a simple tasks manager that I want to build with the MEAN Stack.
I can figure/resolve a simple routing issue. I don't see any error message in the terminal or console except for the 404 client error.
the root path is ok. I get a response back
I use html docs to render the ui for both.
this is how I have set up my server.js
var express = require('express')
var path = require('path')
var bodyParser = require('body-parser')
var index = require('./routes/index');
var tasks = require('./routes/tasks');
var app = express();
const port = '3456'
app.use('/', index)
app.use('api', tasks) <= HERE
//view engine
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')
app.engine('html', require('ejs').renderFile);
//static folder
app.use(express.static(path.join(__dirname, 'client')))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
app.listen(port, function() {
console.log('Starting the server at port' + port );
})
tasks.js
to render the template at the set route
var express = require('express')
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('mongodb://sandy:cookie2080#ds147304.mlab.com:47304/tasklists_21092017', ['tasks'])
router.get('/tasks', function(req, res, next) {
res.send('api')
res.render('tasks.html')
db.tasks.find(function(err, tasks){
if (err) {
res.send('error message ' + err)
}
res.json(tasks)
})
})
module.exports = router;
and, index.js fyi
var express = require('express')
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index.html')
})
module.exports = router;
screenshot at the link below of the 404 error in browser after starting server on port 3456
404 error - screenshot
thanks for the help. I am sure it can be a little detail. it is very hard to debug though.
This error occurs because there's no route that handles the endpoint /api. What you can do here is create a middleware that will handle the /api. You can do it in your tasks.js like this:
tasks.js
router.get('/', function(req, res, next) {
res.send('This is api.')
})
Or if what you want to do is to direct the user from the endpoint /api to /api/tasks then you could do it like this:
router.get('/', function(req, res, next) {
res.redirect('/api/tasks')
})
Hope this helps.
I changed the port number. The issue was that the port 3000, was not responding to the requests, as it was still in use by an older process hence producing the warning
errno: 'EADDRINUSE',.
Just used the port 5000 to try out and it went through smoothly.
By the way I am using vs code.

winston-mongodb log connection fails

My express web app uses Winston for logging, and the logs are saved to a mongolab hosted mongoDB (replica set) using winston-mongodb.
Everything was working fine for a few days, then when traffic picked up a bit the logs just stopped saving/connecting to the DB. Unfortunately this means I have no logs to check to see what went wrong - a frustrating situation. Everything else is still working fine - other collections (like users) are saving and updating correctly, the server is up.
I've tried redeploying/restarting the server to no avail, the logs won't start recording again. I suspect there is some nuanced problem with my server/logger setup, possibly a race condition related to the DB connection, but I'm really lost right now. Here's the code:
//server.js (simplified required modules - only ones possibly relevant to question)
var express = require( 'express' );
var session = require('express-session');
var methodOverride = require('method-override');
var cookieParser = require('cookie-parser');
var mongoose = require( 'mongoose' );
var uriUtil = require('mongodb-uri');
var config = require('config');
var bodyParser = require('body-parser');
var MongoStore = require('connect-mongostore')(session);
var logger = require('./logs/logger.js');
// DATABASE CONNECT
var options = { server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } } };
var mongodbUri = "mongodb://<user>:<pw>#ds012345-a0.mongolab.com:12345,ds012345-a1.mongolab.com:12345/<db>"
//use mongo-uri to make sure url is in the correct format
var mongooseUri = uriUtil.formatMongoose(mongodbUri);
mongoose.connect(mongooseUri, options);
var conn = mongoose.connection;
// __Create server__
var app = express();
conn.on('open', function(e) {
var sessionStore = new MongoStore({ mongooseConnection: mongoose.connections[0] });
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(methodOverride());
app.use(cookieParser());
app.use(session({
store: sessionStore,
secret: config.session.secret,
cookie: {
maxAge: config.session.maxage,
httpOnly: true,
secure: false
//If I set 'secure:true', it prevents the session from working properly.
},
saveUninitialized: true,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use( express.static( path.join( __dirname, 'site') ) );
//Routes
app.use('/api/forgot', controllers.forgotpw);
//etc.
});
conn.on('connected', function(){
//Start server
app.listen(config.port, function() {
logger.info( 'Express server listening on port %d in %s mode', config.port, app.settings.env );
logger.info(process.env.NODE_ENV);
});
});
//logger.js
var winston = require('winston');
var config = require('config');
require('winston-mongodb').MongoDB;
if (process.env.NODE_ENV == 'production') {
var winston = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ level: 'warn' }),
new (winston.transports.MongoDB)({
//db : 'atlas_database',
level : 'debug',
//ssl : true,
dbUri : "mongodb://<user>:<pw>#ds012345-a0.mongolab.com:12345,ds012345-a1.mongolab.com:12345/<db>"
})
]
});
winston.info('Chill Winston, the logs are being captured with production settings');
}
module.exports = winston;
Any thoughts on what is causing the logs to no longer function would be greatly appreciated.
When Winston establishes a connection to a Mongo instance, it looks specifically for the replicaSet flag to determine if the connection is a replica set. Otherwise, it connects to the first host in the dbUri. ( Source: https://github.com/indexzero/winston-mongodb/blob/master/lib/winston-mongodb.js#L28 )
To have configure Winston with a connection that will properly handle failovers, use the following URI:
dbUri : "mongodb://<user>:<pw>#ds012345-a0.mongolab.com:12345,ds012345-a1.mongolab.com:12345/<db>?replicaSet=<replsetname>"
If you ever want to test your code to verify that it can handle a replica set failover gracefully, you can use a testing cluster called flip-flop described here: http://mongolab.org/flip-flop/
(Full Disclosure: I work for MongoLab.)

Nodejs sending email doesnt work from iphone browser

I am using the nodemailer module here: https://github.com/andris9/Nodemailer in order to send an email automatically from a webapp. Having tested it with a PC browser using firefox, everything seems to work fine. However, when I am using an iphone safari to use the app it does not seem to send the email. Ive been scratching my head forever on this and I would be very grateful if anyone knew what was the reason for this!! Note I am using the gmail service, but I have set my gmail so that it sends the message as another address (in this case xyz#abc.com). My code is as follows below:
emailer module:
var nodemailer = require("nodemailer");
function sendEmail(firstname, email){
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "user#gmail.com",
pass: "mypassword"
}
});
smtpTransport.sendMail({
from: "Sender <xyz#abc.com>",
to: email,
subject: "blahblah",
text: "blah blah blah",
}, function(error, response){
if(error){
console.log(error);
} else{
console.log("Success!");
}
});
}
exports.sendEmail = sendEmail;
app module:
var express = require("express");
var fs = require("fs");
var clientEmail = require("./clientEmail.js");
var profileEmail = require("./profileEmail.js");
var app = express();
app.use('/css', express.static(__dirname + '/css'));
app.use('/img', express.static(__dirname + '/img'));
app.use('/javascript', express.static(__dirname + '/javascript'));
app.use(express.bodyParser());
var buf = fs.readFileSync("html/index.html");
var index = buf.toString();
app.get('/', function(request, response) {
response.send(index);
});
app.post('/', function(request, response){
var email = request.body.email;
var name = request.body.name;
var firstname = request.body.firstname;
clientEmail.sendEmail(firstname,email);
response.redirect('/');
});
var port = process.env.PORT || 5000;
app.listen(port, function() {
console.log("Listening on " + port);
});
I have solved the issue. It was unrelated to nodemailer, I was actually using the toSource() function in my javascript which is not safari compatible. thanks all for your help