I am running a websocket (wss) server (with certificate) on port 443. For this i am using the "https" and "ws" module in nodejs (simplified):
require(__dirname + './config.js');
const https = require('https');
const WebSocketServer = require('ws');
const server = new https.createServer({
key: fs.readFileSync('./privkey.pem'),
cert: fs.readFileSync('./fullchain.pem')
});
const wss = new WebSocketServer.Server({server: server});
wss.on("connection", function(socket){
const c_inst = new require('./client.js');
const thisClient = new c_inst();
thisClient.socket = socket;
thisClient.initiate();
socket.on('error', thisClient.error);
socket.on('close', thisClient.end);
socket.on('message', thisClient.data);
});
server.listen(config.port, config.ip);
The wss communication works perfect! But if i open the wss url via https:// in the browser i get a timeout error (Error code 524) because there is no response for a "normal" (https/get) request.
How can i implement a response for this case in my wss server?
I just want to send a response with a simple text or html like "This is a websocket server" or do a redirect to another url if someone connects to the wss socket via browser/https.
Thanks!
See the documentation for HTTPS server on node.
https://nodejs.org/api/https.html#httpscreateserveroptions-requestlistener
You need to add request listener when you create a server.
const server = new https.createServer(
{
key: fs.readFileSync('./privkey.pem'),
cert: fs.readFileSync('./fullchain.pem')
},
(req, res) => {
res.writeHead(200);
res.end('This is a websocket server\n');
// do redirects or whanever you want
}
);
Related
I made a socket.io http server but now I want it to work with https.
I generated a certificate with letsencrypt and I want to use it for my app.
Server code
const fs = require('fs');
const server = require('https').createServer({
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem')
});
const io = require('socket.io')(server, {});
io.on('connection', socket => { console.log(socket.id); });
server.listen(3000);
I'm using socket.io#^2.3.0 and socket.io-client#^2.4.0 for the client
When i try to connect with the client I see no connection / error on the server.
This is how the client looks
const socket = require("socket.io-client")("https://example.com:3000")
socket.on("connect", () => {
console.log("connected")
}
I've also tried with other URLs but still nothing:
const socket = require("socket.io-client")("http://example.com:3000")
const socket = require("socket.io-client")("https://example.com")
const socket = require("socket.io-client")("wss://example.com:3000")
const socket = require("socket.io-client")("wss://example.com")
i am trying to send an https request from my frontend (reactjs) to backend (nodejs/express).
These two both run in localhost.
Back end server code:
const app = require('./app')
const https = require('https');
const fs = require('fs');
const credentials = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
//connect to the database
require('./db')
const port = 8765;
app.get('/', (req, res) => {
res.send('Now using https..');
});
var server = https.createServer(credentials, app);
//var server = https.createServer(app);
// listen for requests
server.listen(port, () => {
console.log("server starting on port : " + port)
});
front end request:
const {data: Sessions}= await axios.get("https://localhost:8765/...");
i am trying to send an https request from my frontend (reactjs) to backend (nodejs/express).
These two both run in localhost.
Back end server code:
const app = require('./app')
const https = require('https');
const fs = require('fs');
const credentials = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
//connect to the database
require('./db')
const port = 8765;
app.get('/', (req, res) => {
res.send('Now using https..');
});
var server = https.createServer(credentials, app);
//var server = https.createServer(app);
// listen for requests
server.listen(port, () => {
console.log("server starting on port : " + port)
});
front end request:
const {data: Sessions}= await axios.get("https://localhost:8765/...");
doing this request from postman with the exact same parameters produces the desired result.However when i try to do this from frontend i get: GET https://localhost:8765/... net::ERR_CERT_AUTHORITY_INVALID in react chrome extention.I believe this is because i am using a self signed certificate and chrome browser can't verify it's validity.
Is there a way to temporarily disable this verification step from chrome?
If not how else can i solve this?
Not : Doing this with HTTP works fine but i need it to be HTTPS.
If your just going to run it on local host one your machine you can disable the setting at chrome://flags/#allow-insecure-localhost in browser.
This will not fix anything in production tho, only for personal use.
I have an https expressjs server with websockets (using the 'ws' package). As far as I understand sockets and ports, I should be able to add a route alongside the websocket connections. The main use-case is so that the server can be curled (none of the ws curl requests I've seen online worked.)
Unfortunately I only have 1 port to use for the server and websockets. How can I set this up so that app and server can both listen on the same port?
I've seen a few comments on SO that indicates that it can be done, but no code examples, or it's for very different packages.
I'm using the 'ws' package: https://www.npmjs.com/package/ws
const port = 8888;
const http = require('http');
const https = require('https');
const express = require('express');
const websocket = require('ws');
const app = express();
app.use( express.static('public') );
app.get('/curl', (req, res) => res.send('Hello World')).listen( port );
const httpsServer = https.createServer( credentials, app );
const wss = new websocket.Server({ server: httpsServer });
httpsServer.listen( port, function listening(){
console.log( 'listening on ' + port );
});
Currently I get the "EADDRINUSE" error since I'm using the same port for two 'servers'.
FOLLOW-UP
Express app doesn't need to also listen if another server is.
To curl https, you have to provide the cert details, or use the '-k' (insecure) method.
Your code shows you trying to start two servers on the same port.
This line creates a new http server and attempts to start it on port 8888:
app.get('/curl', (req, res) => res.send('Hello World')).listen( port );
These lines create a new https server and attempt to start it on port 8888 also.
const httpsServer = https.createServer( credentials, app );
httpsServer.listen( port, function listening(){
console.log( 'listening on ' + port );
});
You cannot do that. If you just want one https server that works for both your web requests and your webSocket (a common way to do things), then change your code to this:
const port = 8888;
const https = require('https');
const express = require('express');
const websocket = require('ws');
const app = express();
app.use( express.static('public') );
app.get('/curl', (req, res) => res.send('Hello World'));
const httpsServer = https.createServer( credentials, app );
const wss = new websocket.Server({ server: httpsServer });
httpsServer.listen( port, function listening(){
console.log( 'listening on ' + port );
});
which just removes the .listen(port) that operates on the app object because that will create an http server and start it on the 8888 port.
Server side code:
var io = require('socket.io').listen(8150);
io.sockets.on('connection', function (socket){
});
Client side code:
var socketIO = io('*.*.*.*:8150');
socketIO.once('connect', function(){
});
On http it's worked on https in same page it not connected.
Searched many examples, but all example for express. I dont create any http server in node.js need only to socket.io work.
When running the client over HTTPS, socket.io is attempting to connect to your server over HTTPS as well. Currently your server is only accepting HTTP connections, the listen(port) function does not support HTTPS.
You'll need to create an HTTPS server and then attach socket.io to it, something like this.
var fs = require('fs');
var options = {
key: fs.readFileSync('certs/privkey.pem'),
cert: fs.readFileSync('certs/fullchain.pem')
};
var app = require('https').createServer(options);
var io = require('socket.io').listen(app);
app.listen(8150);
io.sockets.on('connection', function (socket) {
});
And if you need both HTTP and HTTPS, you can start two servers and attach socket.io to both.
var fs = require('fs');
var options = {
key: fs.readFileSync('certs/privkey.pem'),
cert: fs.readFileSync('certs/fullchain.pem')
};
var httpServer = require('http').createServer();
var httpsServer = require('https').createServer(options);
var ioServer = require('socket.io');
var io = new ioServer();
io.attach(httpServer);
io.attach(httpsServer);
httpServer.listen(8150);
httpsServer.listen(8151);
io.sockets.on('connection', function (socket) {
});
Then on the client side you can determine which port to connect to based on whether the page was accessed over HTTP or HTTPS.
var port = location.protocol === 'https:' ? 8151 : 8150;
var socketIO = io('*.*.*.*:' + port);
socketIO.once('connect', function() {
});
Use letsencrypt with Plesk for a valid SSL certificat.
options = {
key: fs.readFileSync('/usr/local/psa/var/modules/letsencrypt/etc/live/mydomain.com/privkey.pem'),
cert: fs.readFileSync('/usr/local/psa/var/modules/letsencrypt/etc/live/mydomain.com/cert.pem'),
ca: fs.readFileSync('/usr/local/psa/var/modules/letsencrypt/etc/live/mydomain.com/chain.pem'),
rejectUnauthorized: false,
requestCert: true,
agent: false
}
Server:
// Load libraries
var https = require('https');
var fs = require('fs');
var socketio = require('socket.io');
// The server options
var srvAddress = '123.123.123.123';
var srvPort = 8888;
var srvOptions = {
key: fs.readFileSync('ssl/cert.key'),
cert: fs.readFileSync('ssl/cert.crt'),
ca: fs.readFileSync('ssl/cert-ca.crt')
};
// Create a Basic server and response
var app = https.createServer(srvOptions, function(req, res) {
res.writeHead(200);
res.end('Online...');
});
// Create the Socket.io Server over the HTTPS Server
var io = socketio.listen(app, srvAddress);
// Now listen in the specified Port
app.listen(srvPort, srvAddress);
Client:
var socket = require("socket.io-client").connect('https://123.123.123.123:8888', {secure: true});
But client don't connect to server. I tried http instead of https, but the same result.
Server works fine. Without ssl certificate connection works. When try to open via web, then all works too.