10

I'm looking for a way to integrate Node.js + Socket.io + Apache in the following way: I want apache to continue serving HTML / JS files. I want node.js to listen for connection on port 8080. Something like this:

var util = require("util"),
    app = require('http').createServer(handler),
    io = require('/socket.io').listen(app),
    fs = require('fs'),
    os = require('os'),
    url = require('url');

app.listen(8080);

function handler (req, res) {

    fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });

  socket.on('my other event', function (data) {
    socket.emit('ok 1', { hello: 'world' });
  });

  socket.on('clientMSG', function (data) {
    socket.emit('ok 2', { hello: 'world' });
  });

});

if I access a HTML that connect to this server, it works, but I need to go to mydomian.com:8080/index.html. What I want is to be able to go to mydomian.com/index.html. and be able to open a socket connection:

<script>
        var socket = io.connect('http://mydomain.com', {port: 8080});
        socket.on('news', function (data) {
            console.log(data);
            socket.emit('my other event', { my: 'data from the client' });
        });

        socket.on('connect', function (data) {
            console.log("connect");
        });

        socket.on('disconnect', function (data) {
            console.log("disconnect");
        });


            //call this function when a button is clicked
        function sendMSG()
        {
            console.log("sendMSG"); 
            socket.emit('clientMSG', { msg: 'non-scheduled message from client' });
        }

    </script>

In this example I had to use fs.readFile of wont work when I go to the port 8080 in the URL.

Any suggestions? Tks.

oscarm
  • 2,630
  • 6
  • 41
  • 74
  • Try nginx instead of apache, especially if you just want to serve up static files. Apache starts a new thread for every request which is partially counter to the philosophy/reason of using node. – badunk Mar 17 '12 at 09:11

3 Answers3

15

Serve your static content from Apache port 80 and serve your dynamic/data content over a Socket.IO server on port 8080. You don't need the app = require('http').createServer(handler) in your Socket.IO app

Apache port 80 |-------------| clients |------------| Socket.IO port 8080

var io = require('socket.io').listen(8080);

io.sockets.on('connection', function (socket) {
  io.sockets.emit('this', { will: 'be received by everyone'});

  socket.on('clientMSG', function (from, msg) {
    console.log('I received a private message by ', from, ' saying ', msg);
  });

  socket.on('disconnect', function () {
    sockets.emit('user disconnected');
  });
});
EhevuTov
  • 20,205
  • 16
  • 66
  • 71
  • Thanks for the response. I did the change and now looks like the client doesn't get the /socket.io/socket.io.js file. Is this file served by the HTTP server in Node? – oscarm Oct 07 '11 at 16:33
  • 1
    I got it working. changed the path to /socket.io-client/dist/socket.io.js Thanks! – oscarm Oct 07 '11 at 16:39
  • 1
    Yeah, you'll want to serve the socket.io.js from your Apache static server on port 80 and do something like on your client-side code – EhevuTov Oct 07 '11 at 16:41
  • 1
    idk if this will help, but if you npm install socket.io in the current directory, run an app at :8888, you jusy need to script src="http://mydomain:8888/socket.io/socket.io.js", even though it's in node_modules/socket.io/lib/socket.io.js – tester Dec 15 '11 at 08:53
  • 2
    Won't this trigger a "Same origin policy" violation? http://en.wikipedia.org/wiki/Same_origin_policy – stolsvik May 13 '13 at 07:55
  • Yeah, it trigger that now. – user1721713 Feb 01 '14 at 15:00
11

AWS + APACHE + NODEJS + SOCKET.IO + ANGULARJS

SERVER SIDE
This worked for me on a production server running apache on port 80 and NodeJS on port 8000. Change the NodeJS port by your desired option…

  1. Create a folder named “nodejs” for the files of the NodeJS server at /var/www/html
  2. Run Nodejs on a different port than 80, for example port 8000
  3. Execute command: a2enmod proxy_http
  4. Execute command: a2enmod proxy_wstunnel
  5. Put the next 2 lines at the end of the following file: /etc/apache2/apache2.conf

    LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
    LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so 
    
  6. Put the next 12 lines at the end of the following file: /sites-available/000-default.conf
    (If you have a different site created by you, put the lines there)

    RewriteEngine On
    RewriteCond %{REQUEST_URI}  ^socket.io          [NC]
    RewriteCond %{QUERY_STRING} transport=websocket [NC]
    RewriteRule /{.*}       ws://localhost:8000/$1  [P,L]
    
    RewriteCond %{HTTP:Connection} Upgrade [NC]
    RewriteRule /(.*) ws://localhost:8000/$1 [P,L]
    
    ProxyPass /nodejs http://localhost:8000/
    ProxyPassReverse /nodejs http://localhost:8000/
    
    
    ProxyPass /socket.io http://localhost:8000/socket.io
    ProxyPassReverse /socket.io http://loacalhost:8000/socket.io
    
    ProxyPass /socket.io ws://localhost:8000/socket.io
    ProxyPassReverse /socket.io ws://localhost:8000/socket.io
    
  7. sudo service apache2 restart


CLIENT SIDE
I use the following library to implement Socket.io in AngularJS, but I think this guide
is useful too for a basic Javascript implementation of socket.io technology.

To call my PHP server: example.com
To call NodeJS server: example.com/nodejs
To call NodeJS Socket: example.com <---this call will be done by default by the library

I hope help you!

Philip Enc
  • 1,072
  • 15
  • 21
  • Thanks, I was able to solve the problem with running socket.io on an apache server. – prateekkathal Dec 14 '17 at 05:36
  • Using your awesome answer and other research you can find a full sample with certbot, CORS headers, and explanation here (I couldn't have done it without your recomendations!): https://stackoverflow.com/questions/9831594/apache-and-node-js-on-the-same-server/62073028#62073028 – Dr. Aaron Dishno May 28 '20 at 19:37
0

You can continue to serve pages from Apache, but you need to enable CORS in node.js/socket.io:

index.html (served from Apache)

<script src = "https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
<script>
   const socket = io("ws://your.domain.com:8080");
<script>

app.js (In nodejs): (Enable CORS)

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"]
    }
});

http.listen(8080);
Cesar Morillas
  • 707
  • 5
  • 11