Setup-
I have three servers
1] Main Server (https://mainserver.com)
2] Admin Server (https://adminserver.com)
3] Services Server (https://servicesserver.com)
Each of these server run a node.js application. They proxy pipe their respective client angular applications which is served from AWS S3 bucket. When in browser I type https://adminserver.com I get the requested admin application.Each server has nginx reverse proxy server running in front of nodejs server. Backend database is Mongo Db.
Now I had to add push notification to my applications, for which I used socket.io. I setup a socket.io server, and shared session using express session, express-socket.io-session, between my admin server, and socket io server.I worked things out in local host and everything worked fine,I got push notifications working.
I put this socketio server on a new AWS EC2 server (https://socketioserver.com).I used Nginx as reverse proxy in front of my socketio server with ssl on port 443.
Problem-
When my admin application delivered from https://adminserver.com tried to connect using socket by GET method to https://socketserver.com/socket.io, I got the following error.
Error -
XMLHttpRequest cannot load https://socketioserver.com/socket.io/?origin=adminUser&EIO=3&transport=polling&t=LY5-WlP&sid=pUXYOAj2SDammWEQAAAA. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://adminserver.com' is therefore not allowed access. The response had HTTP status code 502.
Reference
nginx code -
server {
listen 443 ssl;
#################################
# SSL key and certificate paths
#################################
ssl_certificate /home/ubuntu/ssl/server-cert.pem;
ssl_certificate_key /home/ubuntu/ssl/server-key.pem;
#################################
# SSL protocol
#################################
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
server_name socketioserver.com;
error_page 502 /errors/502.html;
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://project1_notification_dev_upstream;
proxy_redirect off;
}
}
my socket server code -
////////////////////////////////////////////////////////////////////////////////////
/// Imports
////////////////////////////////////////////////////////////////////////////////////
var express = require('express');
var http = require('http');
var socketApp = express();
var socketServer = http.createServer(socketApp);
var io = require("socket.io")(socketServer);
var session = require('express-session');
var sharedSession = require("express-socket.io-session");
var mongoose = require('mongoose');
var mongoStore = require('connect-mongo')(session);
var path = require('path');
var socketPORT = 1367;
var requestPORT = 2389;
var requestApp = express();
///////////////////////////////////////////
// Configuration Files
///////////////////////////////////////////
var configMongoDb = require(
'./server/configurationDetails/mongoDb/mongoDb'
);
var serverConfig = require(
'./server/configurationDetails/server/serverConfig'
);
///////////////////////////////////////////////////////////////////////////////////
// Only one global variable giving th root folder of the server
///////////////////////////////////////////////////////////////////////////////////
global.serverRoot = path.resolve(__dirname);
global.clientsGlobal = {};
//////////////////////////////////////////////////////////////////
/// Set up Mongo Db connection
//////////////////////////////////////////////////////////////////
/// Debug Variables
/// If localDebug = true, use local Database
/// If liveDebug = true, use server database
/// else use main database
//////////////////////////////////////////////////////////////////
var mongoDbUrl = "";
if( serverConfig.mode === "local" ){
mongoDbUrl = configMongoDb.localUrl;
}else if( serverConfig.mode === "liveDebug" ){
mongoDbUrl = configMongoDb.liveDebugUrl;
}else if(
serverConfig.mode === "productionA"
||
serverConfig.mode === "productionB"
){
mongoDbUrl = configMongoDb.productionUrl;
}
mongoose.connect(
mongoDbUrl,
{
config: {
autoIndex: true
}
},
function (err) {
if (err) {
console.log("error in connecting to mongo db");
console.log(err);
}else{
console.log("Connected To Mongo DB");
}
}
);
////////////////////////////////////////////////////////////////////////////////////
var newSession = session(
{
secret : configMongoDb.mongoSessionSecret,
resave : false,
saveUninitialized : false,
store : new mongoStore(
{
mongooseConnection : mongoose.connection
}
)
}
);
//////////////////////////////////////////////////////////////////////////////////////
requestApp.get('/userNotification',function(req,res){
var userId = req.query.userId;
var data = req.query.data;
var socketArray = clientsGlobal[userId+"_mainUser"];
if (!Array.isArray(socketArray)) {
return res.status(200);
}
for(var i = 0 ; i < socketArray.length ; i++){
socketArray[i].emit(userId + "_mainUser" , data);
}
return res.status(200).send("OK");
});
requestApp.get('/adminUserNotification', function(req,res){
var userId = req.query.userId;
var data = req.query.data;
var socketArray = clientsGlobal[userId+"_adminUser"];
if (!Array.isArray(socketArray)) {
return res.status(200);
}
for(var i = 0 ; i < socketArray.length ; i++){
socketArray[i].emit(userId + "_adminUser" , data);
}
return res.status(200).send("OK");
});
requestApp.get('/serviceProviderNotification',function(req,res){
var userId = req.query.userId;
var data = req.query.data;
var socketArray = clientsGlobal[userId+"_serviceProvider"];
if (!Array.isArray(socketArray)) {
return res.status(200);
}
for(var i = 0 ; i < socketArray.length ; i++){
socketArray[i].emit(userId + "_serviceProvider" , data);
}
return res.status(200).send("OK");
});
var requestServer = http.createServer(requestApp);
requestServer.listen(requestPORT , function(){
console.log("Request Server Listening");
});
io.use(sharedSession(newSession));
io.on("connection", function(socket) {
var origin = socket.handshake.query.origin;
console.log(socket);
console.log(socket.handshake.session);
if(clientsGlobal[socket.handshake.session.passport.user+"_"+origin] === undefined){
if(clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin] === undefined){
clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin] = [];
clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin].push(socket);
}else{
clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin].push(socket);
}
}
socket.on("disconnect" , function(){
for(var i = 0; i < clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin].length ; i++ ){
if( clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin][i].id === socket.id ){
clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin].splice(i, 1);
break;
}
}
if( clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin].length === 0 ){
delete clientsGlobal[socket.handshake.session.passport.user._id+"_"+origin];
}
});
});
socketServer.listen(socketPORT , function(){
console.log("socketServer running");
});