Hosting WebSocket apps in IIS using iisnode

Hero Image

In this post I explain how to configure a node.js application to use of WebSockets when hosting it in IIS 8 using iisnode. This complements a recent post in which I showed how to host node.js WebSocket applications in IIS on Windows using iisnode and faye-websocket module.

The complete code of the sample for self-hosting and IIS hosting of and faye-websocket in IIS using iisnode is available at

From Zero to Divine in  Seven Seconds

You need Windows 8 or Windows 2012 machine with IIS 8 and iisnode installed.

Clone the Dante sample, install dependencies, and set up IIS virtual directory pointing to the code of the sample:

   git clone  
npm install  

Then navigate to the sample at http://localhost/dante/server-socketio.js. You should see Dante’s Divine Comedy streamed to you over websockets from a application hosted in IIS 8 using iisnode, one stanza every 2 seconds:


You can see four HTTP requests being made. The first one targets the node.js application server-socketio.js and returns the HTML page with client side JavaScript. The page requests the client library from the server, which is the second HTTP call. Next, the client side JavaScript on the page performs the handshake (3rd HTTP requests). Finally, a WebSocket connection is established and the Dante’s Divine Commedy is streamed from the server as discrete WebSocket messages over that single connection.

Under the hood

Hosting node.js apps in IIS using iisnode requires some extra steps compared to self-hosting such apps. Unlike in a typical self-hosting case, node.js apps hosted in a IIS virtual directory own only a subset of the URL space, and must be adequately configured to that effect. In addition, IIS must be told which requests constitute traffic and must be handled by iisnode as opposed to other built-in IIS handlers (e.g. static file handlers).

This explanation assumes the node.js application is hosted in a IIS virtual directory named ‘dante’ as opposed to the root of an IIS website. The latter case is simpler to configure, with only required changes being the changes in web.config described below.

Below are the key components of the configuration. Full source code of the sample is at


There are three aspects that must be configured in web.config: handler registration, URL rewrite rules, and IIS wesocket module configuraiton.

First, you must inform IIS that the file is a node.js application and must be handled by iisnode. Without this, IIS would try to serve the file as a client side JavaScript using the static file handler:

   <add name="iisnode-socketio" path="server-socketio.js" verb="*" modules="iisnode" />  

Then, the URL rewrite module must be informed that all HTTP requests that start with the ‘’ segment constitute node.js traffic and should be redirected to the server-socketio.js as the entry point of the node.js application. Without this, IIS would attempt to map these requests to other handlers, and most likely respond with a failure code:

          <rule name="LogFile" patternSyntax="ECMAScript">  
               <match url=""/>  
               <action type="Rewrite" url="server-socketio.js"/>  

Lastly, the built-in WebSocket module that IIS 8 ships with must be turned off, since otherwise it would conflict with the WebSocket implementation provided by on top of the raw HTTP upgrade mechanism node.js and iisnode support:

<webSocket enabled="false" />

The complete web.config is at

The server

The server code must configure to inform it that the node.js application owns just a subset of the URL space as a result of being hosted in IIS virtual directory. This means that traffic that the server normally listens to on the / path is going to arrive at /dante/

io.configure(function() {  
    io.set('transports', [ 'websocket' ]);  
    if (process.env.IISNODE_VERSION) {  
        io.set('resource', '/dante/');  

Notice this configuration change in is only made when the application is hosted in IIS; the same code base of the sample can also be self-hosted, in which case the configuration is left unmodified.

The full code of the server is at

The client

The client code must contain configuration change corresponding to the server, otherwise client library would by default assume the traffic should be sent to the / path on the server:

var address = window.location.protocol + '//' +;  
var details = {  
    resource: (window.location.pathname.split('/').slice(0, -1).join('/') + '/').substring(1)  
var client = io.connect(address, details); 

Notice that this client code works correctly both when the server is self-hosted or hosted in a IIS virtual directory. This is because the configuration sets the URL paths relative to the pathname of the original request that rendered the HTML page. In the self-hosted case, the original page is rendered from http://localhost:8888/, and consequently’s resource property is set to ‘’. In the IIS hosted case, the original request is rendered from http://localhost/dante/server-socketio.js, and as a result the resource property will be set to ‘dante/’. This allows the client code to be agnostic to how the server is hosted.

The full code of the client is at



Most Recent

23 June 2022
Is EdgeDB the Future?

EdgeDB solves some design flaws of relational and No-SQL databases. Read the differences between EdgeDB, MongoDB, and GraphQL and the best use cases for EdgeDB.

22 June 2022
Trello API Limits, 5 Best Practices to Avoid Rate Limiting

Third-party APIs like the Trello API can make life easier for developer. We'll discuss best practices to avoid rate limits in the Trello API.

22 June 2022
Using the Google Calendar API in React.js, An In-Depth Guide

We'll build a simple React app that uses Google Calendar API and that lists and adds events to your calendar. Let’s dive in.