socket.io routing issue with a node.js express 3 app running in a virtual directory with iisnode

Errors:

Trying to access http://localhost/appDirectory/socket.io gives:
Cannot GET /appDirectory/socket.io

Or to put it another way when trying to load the client file on the page I get this error:
GET http://localhost/appDirectory/socket.io/socket.io.js 404 (Not Found)

If I load the client file as static content the connect line produces this error:
GET http://localhost/appDirectory/socket.io/1/?t=1365535131937 404 (Not Found)

Server code:

var express = require('express'),
namespace = require('express-namespace'),
routes = require('./routes'),
http = require('http'),
app = express(),
server = app.listen(process.env.PORT),
io = require('socket.io').listen(server);
var appDir = '/appDirectory';

app.configure(function(){
  app.set('env', process.env.NODE_ENV || 'development');
  app.set('/views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(app.router);
  app.use(appDir, require('stylus').middleware(__dirname + '/public'));
  app.use(appDir, express.static(path.join(__dirname, '/public')));
});

app.get(appDir + '/', routes.index);

io.sockets.on('connection', function (socket) {
  socket.emit('message', 'lol');
});

Client code:

<script src="/appDirectory/socket.io/socket.io.js"></script>
<script type="text/javascript">
  var socket = io.connect(appDir, { resource: appDir.substring(1) + '/socket.io' });
  socket.on('connect', function () {
    console.log('connected');
  });
</script>

The web config file that's getting this to work is...

Web.config:

<configuration>
<system.webServer>
  <handlers>
    <add name="iisnode" path="app.js" verb="*" modules="iisnode" />
  </handlers>
  <iisnode loggingEnabled="true" debuggingEnabled="true" debuggerPathSegment="debug" />
  <rewrite>
    <rules>
      <clear />
      <rule name="Debug" patternSyntax="Wildcard" stopProcessing="true">
        <match url="app.js/debug*" />
        <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
        <action type="None" />
      </rule>
      <rule name="app" patternSyntax="Wildcard">
        <match url="*" negate="false" />
        <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
        <action type="Rewrite" url="app.js" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>
</configuration>

My gut feeling is that the express routing is interfering with the socket.io routing or that the socket.io routing is not compatible with the virtual directory. I did see some mention of namespacing with socket.io and I did try the following...

io.of(appDir).on('connection', function (socket) {
  socket.emit('message', 'lol');
});

But that didn't seem to fix the problem.

I have tried a number of different things on the client code side but I don't think that is the root problem or the http://localhost/appDirectory/socket.io/socket.io.js would be working.

The application is running as a virtual directory and is built on:

- node.js 0.10.3 for windows
- iis 7
- iisnode 0.2.4
- express.js 3.0.0rc1  
- jade  
- socket.io  

The module "express namespace" seems to make things work.

I am aware that iisnode was "designed" to be run as a separate site and I'm also aware that express doesn't like being in a virtual directory, but I am pretty sure this is possible.

Interesting update!

Changing the line:

io = require('socket.io').listen(server);

To:

io = require('socket.io').listen(server, { resource: appDir + '/socket.io' });

Causes the iis worker process w3wp.exe to crash...
As seen here http://i.imgur.com/65RGia3.png?1

However the url http://localhost/appDirectory/socket.io then seems to work.

Failed attempts at fixing this FYI:

  • adding the web.config setting for iisnode nodeProcessCountPerApplication="1"

Possible solution:

If you are stuggling with this same issue, I found this which might help you...
http://tomasz.janczuk.org/2013/01/hosting-socketio-websocket-apps-in-iis.html

A little bit of a stab in the dark, but if you're using Express 3.x, your problem may be that you're using the older Express 2.x syntax for hooking up Socket.io with Express.

See: https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x#socketio-compatibility for the new integration method.

It looks like you're on the right track. Using the following configuration, it works for me (not using IIS, though):

// server
io = require('socket.io').listen(server, { resource : '/appDirectory/socket.io' });

// client
<script src="/appDirectory/socket.io/socket.io.js"></script>
...
var socket = io.connect('', { resource: 'appDirectory/socket.io' });

I wonder why your IIS process is crashing, could you post the image elsewhere (Dropbox, free image hoster) perhaps?