node.js Socket.io cors from null - node.js

I created a server over ssl with Node.js and I will use socket.io.
When I type https://socket.com/test on the browser via my code below, it works. There is no problem.
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
var io = require('socket.io')(https);
// This line is from the Node.js HTTPS documentation.
var options = {
key: fs.readFileSync('/etc/ssl/ssl-keys/crunchsystem/key.pem'),
cert: fs.readFileSync('/etc/ssl/ssl-keys/crunchsystem/cert.pem')
};
var app = express();
// Create a service (the app object is just a callback).
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.get('/test',function(request, response) {
response.send(JSON.stringify({ status:'ok' }));
});
app.post('/order', function(request, response) {
if (request.body.restaurant_code !== undefined) {
io.of('/'+request.body.restaurant_code).emit('GetOrder', request.body.data);
}
response.send(JSON.stringify({ status: request.body.restaurant_code }));
});
// Create an HTTP service.
http.createServer(app).listen(80);
// Create an HTTPS service identical to the HTTP service.
https.createServer(options, app).listen(443);
However ... When I try to listen to the channel, it keeps giving a cors error.
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<script>
var socket = io.connect('https://socket.crunchsystems.com/foo');
console.log(socket);
socket.on('GetOrder', msg => {
console.log(msg)
})
</script>
from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
There's always this error.How do I solve this error? Can you help me?
I've tried all kinds of solutions, I've tried everything that happens on the Internet.

Related

Putting socket.io behind a reverse proxy?

I recently decided to learn socket.io, to make something real-time. I wrote something up, following the Get Started page on the site, and tested it locally until I got it working properly.
I uploaded it to my server using the same process as anything else. I ran it on port 8002, and added it to my reverse proxy (using http-proxy-middleware) under /pong/*. I then proxied /socket.io/* to port 8002 before it worked. However after inspection with Firefox I noticed that socket.io was only using polling as a transport method and not websockets, and after some further thought I decided that sending /socket.io/* to 8002 is not going to be good when using socket.io on other projects in the future.
So I ask, how do I get multiple socket.io programs running behind a reverse proxy, using websockets as a for transport?
proxy.js
const express = require("express")
const fs = require('fs');
const http = require('http');
const https = require('https');
const proxy = require('http-proxy-middleware');
const privateKey = fs.readFileSync('/etc/[path-to- letsencrypt]/privkey.pem', 'utf8');
const certificate = fs.readFileSync('/etc/[path-to-letsencrypt]/cert.pem', 'utf8');
const ca = fs.readFileSync('/[path-to-letsencrypt]/chain.pem', 'utf8');
var credentials = {key: privateKey, cert: certificate, ca: ca};
var app = express();
app.use(function (req, res, next) {
console.log(req.url)
next()
})
app.use("/pong/*", proxy({ target: "http://localhost:8002", pathRewrite: {"^/pong": ""}, ws:true, changeOrigin: true }))
app.use("/pnw/war/*", proxy({ target: "http://localhost:8000" }))
app.use("/pnw/nation/*", proxy({ target: "http://localhost:8001" }))
app.use(express.static("./static"))
https.createServer(credentials, app).listen(443);
// Redirect all HTTP traffic to HTTPS
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
res.end();
}).listen(80);
pong.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http, {
path: "/pong/"
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
http.listen(8002, function(){
console.log('listening on *:8002');
});
index.html
<script src="/pong/socket.io.js"></script>
<script>
var socket = io({
// transports: ['websocket'], upgrade: false, (using for testing)
path:"/pong"
})
// ...
</script>
What I have currently comes from following the answer to this question:
Setting up multiple socket.io/node.js apps on an Apache server?
However in the firefox console I get a warning which reads:
Loading failed for the <script> with source “https://curlip.xyz/pong/socket.io.js”, followed by an error io is not defined. In the network tab getting socket.io.js is showing a 404.
So what I believe is happening is that because express is capturing the requests for /, socket.io cannot (for some reason) server socket.io.js. However when I changed / to /index.html and loaded that there was no change.
So I did some more research and came upon a solution. I opened the port 8002 on my EC2 so that I could poke around looking for socket.io.js.
Essentially what I found is socket.io.js was located at /pong/pong/socket.io.js because I set path in pong.js to "pong", which, in hindsight make sense, the proxy adds one "pong", while socket.io itself is capturing "/pong".
Knowing this I removed the path option in pong.js, so that socket.io.js can be found at /pong/socket.io/socket.io.js. I then made the client point to this by changing the script tag and path option in index.html.
pong.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
http.listen(8002, function(){
console.log('listening on *:8002');
});
index.html
<script src="/pong/socket.io/socket.io.js"></script>
var socket = io({
path:"/pong/socket.io/"
})

node js ssl certificates issue

When I run the code like below on Node.JS v0.10.36 - server responds on https request, but then I run the same code on Node.JS v4.2.1 - server doesn't respond at all,however in that time browser does not "say" that anything goes wrong - it just continues to load the page. Should I rewrite the code in some way?
var express = require('express');
var https = require('https');
//var http = require('http');
var fs = require('fs');
var crypto=require('crypto')
var app = express();
var ssl_conf=require(__dirname+'/config/ssl.json');
var secureContext = {}
try{
for(var domain in ssl_conf){
secureContext[domain]=getSecureContext(ssl_conf[domain].domain);
}
}
catch(err){
console.log('error with ssl.config file '+err);
}
function getSecureContext (domain) {//returns secure context
return crypto.createCredentials({
key: fs.readFileSync('./ssl/'+domain+'.key'),
cert: fs.readFileSync('./ssl/'+domain+'.crt')
}).context;
}
var options = {
SNICallback: function (domain) {
return secureContext[domain];
},
//in case SNI is not available use this cert
cert: fs.readFileSync('./ssl/2_helena.softpro.ua.crt'),
key: fs.readFileSync('./ssl/2_helena.softpro.ua.key')
}
app.get('/',function(req,res){//simple route
res.send("your domain is "+req.hostname);
})
https.createServer(options, app).listen(443,function(){//run server
console.log('https server running on 443')
});
In recent version 12.0.0 + next code is ok
var options = {
SNICallback:function(domain,cb){
var ctx= tls.createSecureContext(
secureContext[domain]//{key:<Buffer>,cert:<Buffer>}
).context
if(cb)
cb(null,ctx)
else
return ctx;
}
}

Cannot open site with https server using Express

var fs = require('fs'),
https = require('https'),
express = require('express'),
app = express();
https.createServer({
key: fs.readFileSync('./ssl/key.pem'),
cert: fs.readFileSync('./ssl/cert.pem')
}, app).listen(55555);
app.get('/', function (req, res) {
res.header('Content-type', 'text/html');
return res.end('<h1>Hello, Secure World!</h1>');
});
I tried many times about using https server based on express, while I still cannot open the site, for example using Chrome:
It says "No data received" and "ERR_EMPTY_RESPONSE".
So it is listening, but the response cannot be sent to client, why?
Thank you!

expressjs 4.x and https, generate key and certificate

I want to create an https server with express 4.x. Even if a lot of code found on google is based on express 3.x I think I made the port correctly.
Even if I tried to goole it is not very clear to me how to generate the keys. Without the key I'm expecting 401.
I tried with the script found in this gist. But I'm keeping on receiving the error Error: DEPTH_ZERO_SELF_SIGNED_CERT.
I'd like to test it both with curl, request, and super test.
This is what actually I have:
server.js
var express = require('express')
, https = require('https')
, fs = require('fs');
var privateKey = fs.readFileSync('./server/server-private-key.pem').toString();
var certificate = fs.readFileSync('./server/server-certificate.pem').toString();
var options = {
key : privateKey
, cert : certificate
}
var app = express();
app.get('/', function(req, res) {
req.client.authorized ?
res.json({"status":"approved"}) :
res.json({"status":"denied"}, 401);
});
server = https.createServer(options,app);
var port = 12345;
server.listen(port, function(){
console.log("Express server listening on port " + port);
});
client.js
var https = require('https');
var fs = require('fs');
var options = {
host: 'localhost',
port: 12345,
method: 'GET',
path: '/',
key: fs.readFileSync('./client/client-private-key.pem'),
cert: fs.readFileSync('./client/client-certificate.pem'),
headers: {}
};
var req = https.request(options, function(res) {
console.log('dudee');
console.log(res);
});
req.end();
With cURL you can use the -k flag to bypass the self-signed cert problem.
With request you can just set rejectUnauthorized: false in the request options.

Intercept HTTP responses on an HTTPS server in Node.JS and Express

I'm just starting with node.js and express and I'm doing a simple HTTPS server. I've been working with nginx for some time and when I make an HTTP request to an HTTPS endpoint I get a "400 Bad Request" error. However, when using node.js the request never finishes.
How can I intercept an HTTP request in Express to be able to generate the "400 Bad Request" response?
This is my code:
var express = require('express');
var https = require('https');
var fs = require('fs');
var port = process.env.PORT || 8080;
var tls_options = {
key: fs.readFileSync('certs/server.key'),
cert: fs.readFileSync('certs/server.crt'),
ca: fs.readFileSync('certs/ca.crt'),
requestCert: true,
};
var app = express();
var router = express.Router();
router.get('/', function(req, res) {
res.json({ message: 'Checkpoint!!' });
});
app.use('/', router);
var secureServer = https.createServer(tls_options, app);
secureServer.listen(port);
console.log('Listening on port ' + port);
Until now the only thing I've been able to use is getting a 'connection' event every time a request arrives to the server:
secureServer.on('connection', function (stream) {
console.log('someone connected!');
});
Done. In fact, an HTTP request to an HTTPS socket ends after the default 120secs TLS handsahke timeout. This way I can end the request without waiting. I include the solution I used just for future references if anything needs the same functionality.
var secureServer = https.createServer(options, app);
secureServer.on('connection', function(socket) {
socket.on('data', function(data) {
var first_line = data.toString().split('\r\n')[0];
var pattern = /\bhttp\/1\.[01]$\b/i;
if (pattern.test(first_line)) {
var headers = {};
headers['Date'] = new Date().toUTCString();
headers['Connection'] = 'close';
var headers_string = '';
for (var name in headers) {
headers_string = headers_string + '\r\n' + name + ': ' + headers[name];
}
socket.end('HTTP/1.1 400 Bad Request' + headers_string);
}
});
There isn't a way of starting both HTTP and HTTPS servers on the same port. What most people do is either:
Start two servers (one HTTP and one HTTPS) on different ports, and redirect the HTTP traffic to HTTPS. Using Express it would mean the additional code:
// create two ports, one for HTTP and one for HTTPS
var port = process.env.PORT || 8080;
var httpsPort = 8081;
// redirect all HTTP requests to HTTPS
app.use(function(req, res, next) {
var hostname;
if (!req.secure) {
hostname = req.get("host").split(":")[0];
return res.redirect(["https://", hostname, ":", httpsPort, req.url].join(""));
}
next();
});
app.listen(port); // listen on HTTP
https.createServer(tls_options, app).listen(httpsPort); // listen on HTTPS
Or they use nginx or apache to handle outside connections (both HTTP and HTTPS) and redirect traffic to the Node server (which can then just run on HTTP).

Resources