I am trying to create a secure node.js server to use with my site that is using ssl (https).
const crypto = require('crypto'),
fs = require("fs"),
http = require("http");
var privateKey = fs.readFileSync('/home/privatekey.pem');
var certificate = fs.readFileSync('/home/certificate.pem');
var credentials = crypto.createCredentials({key: privateKey.toString(), cert: certificate.toString()});
var handler = function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
};
var server = http.createServer();
server.setSecure(credentials);
server.addListener("request", handler);
server.listen(8084);
But when I start my server, I get the following error:
node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Object #<Server> has no method 'setSecure'
at Object.<anonymous> (/home/meshdev/public_html/js/node/server/test.js:16:8)
at Module._compile (module.js:380:26)
at Object..js (module.js:386:10)
at Module.load (module.js:312:31)
at Function._load (module.js:273:12)
at Array.<anonymous> (module.js:399:10)
at EventEmitter._tickCallback (node.js:108:26)
My server works great without the server.setSecure(credentials); line. I am running node.js(V0.4.1).
I would appreciate any suggestions.
Thank you.
HTTPS implementation was re-done in Node.JS 0.4. See the corresponding docs at nodejs.org.
Example from the docs:
var tls = require('tls');
var fs = require('fs');
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};
tls.createServer(options, function (s) {
s.write("welcome!\n");
s.pipe(s);
}).listen(8000);
this setup allowed me to connect to my socket.io server ssl (HTTPS/WSS)
http=require('https'),io=require('socket.io'),fs=require('fs');
var privateKey = fs.readFileSync('ssl/nginx.key');
var certificate = fs.readFileSync('ssl/nginx.crt');
var options = {key: privateKey,cert: certificate};
var server = http.createServer(options);
server.listen(3000);
io = io.listen(server);
I have worked on the https secure with the ssl here is the working code for making the https and http
var fs = require('fs');
var http = require('http');
var https = require('https');
var debug = require('debug')('expressapp');
var app = require('../app');
var CONSTANTS = require('../config/CONSTANTS.js');
var AWS = require('aws-sdk');
var certificate =fs.readFileSync('ssl/server.crt',{encoding:'utf8'},function(err, data ) {
console.log( data );});
var privateKey = fs.readFileSync('ssl/server.key',{encoding:'utf8'},function(err, data ) {
console.log( data );});
var credentials = {
key: privateKey,
cert: certificate,
rejectUnauthorized:false
};
// UNCOMMENT THIS LINE AFTER INSTALLING CA CERTIFICATE
//credentials.ca = fs.readFileSync('ssl/server.crt', 'utf8');;
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(CONSTANTS.PORT.HTTP, function() {
console.log('HTTP server listening on port ' + CONSTANTS.PORT.HTTP);
}) ;
httpsServer.listen(CONSTANTS.PORT.HTTPS, function() {
console.log('HTTPS server listening on port ' + CONSTANTS.PORT.HTTPS);
});
Related
My requirement is this that if some users connect through WS or WSS they can communicate with each other.Now if i run node server for WSS it does not run over HTTP and if run for WS then it does not Connect on HTTPS .Any solution?
After a long research at last i find this solution and is working for me as i was requiring.This is my sever.js file.
/**
Before running:
> npm install ws
Then:
> node server.js
> open http://localhost:8080 in the browser
*/
const http = require('http');
const fs = require('fs');
const ws = new require('ws');
//for wss
const https = require('https');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const wss = new ws.Server({noServer: true});
const clients = new Set();
function accept(req, res) {
if (req.url == '/ws' && req.headers.upgrade &&
req.headers.upgrade.toLowerCase() == 'websocket' &&
// can be Connection: keep-alive, Upgrade
req.headers.connection.match(/\bupgrade\b/i)) {
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onSocketConnect);
} else if (req.url == '/') { // index.html
fs.createReadStream('./index.html').pipe(res);
} else { // page not found
res.writeHead(404);
res.end();
}
}
function onSocketConnect(ws) {
clients.add(ws);
log(`new connection`);
ws.on('message', function(message) {
log(`message received: ${message}`);
message = message.slice(0, 500); // max message length will be 50
for(let client of clients) {
client.send(message);
}
});
ws.on('close', function() {
log(`connection closed`);
clients.delete(ws);
});
}
let log;
if (!module.parent) {
log = console.log;
// for wss
https.createServer(options,accept).listen(8443);
http.createServer(accept).listen(8080);
} else {
// to embed into javascript.info
log = function() {};
// log = console.log;
exports.accept = accept;
}
Now WS and WSS links will run from same file.For WSS port will be 8443 and for WS 8080,Other link will remain same.
For WSS these are required
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
and here is help for generating these files
//how-to-get-pem-file-from-key-and-crt-files
How to get .pem file from .key and .crt files?
openssl rsa -inform DER -outform PEM -in server.key -out server.crt.pem
Let me know if facing any issue.
So basically I've been trying to get https working with my socket.io
server code:
var express = require('express');
var app = express();
var httpsapp = express();
var https = require('https');
var fs = require("fs");
var server = https.createServer({
key: fs.readFileSync('key.pem').toString(),
cert: fs.readFileSync('cert.crt').toString(),
ca: fs.readFileSync('ca.pem').toString()
}, httpsapp);
var io = require('socket.io').listen(server);
var io = io.listen(8080);
(A whole bunch of socket.on's and one that sends one per second (they did work without https))
Client code:
var socket = io('https://server.com:8080', {secure: true});
I'm being filled to the brim with ERR_SSL_PROTOCOL_ERROR errors
Does anyone know how to fix this?
Edit: The certs are ones from cloudflare
In my app, I send a post request to the server with data containing a CSV file:
$.ajax({
type:"POST",
contentType: "application/json",
url:"/",
data: JSON.stringify({fileData:My_CSV_FILE}),
success: function(csvJson) {
console.log('in the done block!');
//can use csvJson in this handler
});
});
Note: I'm posting to the home route, and I am able to get a response with the data converted from the server. The problem is that whether I run on localhost or Heroku, I am only able to trigger the POST request once, then I have to restart the server (even if I refresh the page). So I know the issue is with my route somewhere:
UPDATED TO INCLUDE FULL SERVER FILE:
'use strict';
const express = require('express');
const csvtojson = require('csvtojson');
const PORT = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const Converter = require('csvtojson').Converter;
var converter = new Converter({});
let app = express();
app.use(bodyParser.json({limit: '300kb'}));
app.use(express.static(__dirname +'/public'));
app.post('/',function(req,res) {
var csvFile = (req.body.fileData);
converter.fromString(csvFile, function(err, result) {
if(!err) {
console.log(result);
res.json(result);
}else {
res.json({error: 'Could not convert'});
}
})
});
app.listen(PORT, () => {
console.log(`app listening on port ${PORT}`);
});
I'm using Express 4. Again, everything works, but only once. When I run Heroku logs, or check the console on localhost I get:
Error: Can't set headers after they are sent.
But I don't understand how I'm re-setting them.
If wanting to run on localhost, here is a link to the projects github: https://github.com/qctimes/calendar_export
You should move the converter instantiation to be done inside the app.post callback method. This way it will instantiate a new object at every request.
This is is how your code should be:
'use strict';
const express = require('express');
const csvtojson = require('csvtojson');
const PORT = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const Converter = require('csvtojson').Converter;
let app = express();
app.use(bodyParser.json({limit: '300kb'}));
app.use(express.static(__dirname +'/public'));
app.post('/',function(req,res) {
var csvFile = (req.body.fileData);
var converter = new Converter({}); // instantiation is done here
converter.fromString(csvFile, function(err, result) {
if(!err) {
console.log(result);
res.send(result);
}else {
res.send({error: 'Could not convert'});
}
});
});
app.listen(PORT, () => {
console.log(`app listening on port ${PORT}`);
});
So i am trying to publish an node js app , but it is returning me 404 for my post calls . It works perfectly on localhost. This is my code :
app.js
var express = require('express');
var path = require('path');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var server = require('http').Server(app);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, '/')));
app.use('/', routes);
app.use('/users', users);
server.listen(process.env.PORT || 3000,function(){
console.log("Working on " + process.env.PORT);
});
module.exports = app;
This is my routes index.js
var express = require('express');
var request = require('request');
var path = require('path');
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
var jsonParser = bodyParser.json()
app.use(bodyParser.json())
var Connection = require('tedious').Connection;
var databaseConnection
var config = {}
var Connection = require('tedious').Connection;
var config = {
userName: 'asdasd',
password: 'password',
server: 'server',
options: {encrypt: true, database: 'asdasd'}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
console.log("Connected");
});
router.post('/call',jsonParser, function(req,res){
res.send('someresponse')
}
I am simply calling /call through ajax , but it keeps throwing 404 not found.
What am i doing wrong ? It doesnt make sense to me to work on localhost but not online.
If you are using express you cann start server directly with express.
app.listen(port)
If you want to do it with nodejs http you also have to set the port nodejs should listen to.
nodejs http
express app.listen
The problem was my auto generated web config was not doing its job , i have swaped it with another one i found on internet
https://github.com/projectkudu/kudu/wiki/Using-a-custom-web.config-for-Node-apps
Just changed from server.js to app.js
I need to share session between sockets and express js.
I've tried to make this example work: http://www.danielbaulig.de/socket-ioexpress/ without success. Web browser return
GET localhost:8000/socket.io/1/?t=1354005884872 500 (Internal
Server Error)
on session start. I get server side error:
warn - handshake error Error
Server side script:
var express = require('express')
, util = require('util')
, connect = require('express/node_modules/connect')
, parseCookie = connect.utils.parseCookie
, MemoryStore = connect.middleware.session.MemoryStore
, store;
var app = express()
, http = require('http')
, server = http.createServer(app)
, io = require('socket.io').listen(server);
var connect = require('express/node_modules/connect')
, util = require('util')
, cookie = require('cookie')
, parseCookie = cookie.parse
, MemoryStore = connect.middleware.session.MemoryStore
, store;
app.configure(function () {
app.use(express.cookieParser());
app.use(express.session({
secret: 'secret'
, key: 'express.sid'
, store: store = new MemoryStore()
}));
app.use(function (req, res) {
res.send('Hello, your session id is ' + req.sessionID);
});
});
io.set('authorization', function (data, accept) {
if (!data.headers.cookie)
return accept('No cookie transmitted.', false);
data.cookie = parseCookie(data.headers.cookie);
data.sessionID = data.cookie['express.sid'];
store.load(data.sessionID, function (err, session) {
if (err || !session) return accept('Error', false);
data.session = session;
return accept(null, true);
});
}).sockets.on('connection', function (socket) {
var sess = socket.handshake.session;
socket.log.info(
'a socket with sessionID'
, socket.handshake.sessionID
, 'connected'
);
socket.on('set value', function (val) {
sess.reload(function () {
sess.value = val;
sess.touch().save();
});
});
});
app.use(count);
// custom middleware
function count(req, res) {
req.session.count = req.session.count || 0;
var n = req.session.count++;
res.send('viewed ' + n + ' times\n');
}
server.listen(8000);
Client side script:
<%= javascript_include_tag "http://localhost:8000/socket.io/socket.io.js" %>
var socket = io.connect('http://localhost:8000');
socket.io v0.9.11, express.js v3.0.3, connect v2.7.0, cookie v0.0.5
I wish you can help me.
Just came across a project that might help simplify everything for you. Express.io combines express and socket.io and includes a bunch of easy to get working examples:
https://github.com/techpines/express.io
I've only toyed with it a little myself, but it looked promising. Hope this helps.