Monday, August 29, 2011

Using URL rewriting with node.js applications hosted in IIS using iisnode

In my last post I introduced the iisnode project which allows hosting node.js applications in IIS on Windows. In this article I discuss using URL rewriting with node.js apps hosted in IIS, functionality necessary in all but the most trivial IIS hosted node.js applications.

The problem

Consider the hello world sample code, saved in the hello.js file in IIS virtual directory:

var http = require('http');

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello, world! [helloworld sample]');
}).listen(process.env.PORT);

along with the following web.config that registers the iisnode module as a handler of the hello.js file, therefore indicating it is a node.js application:

<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
</handlers>
</system.webServer>
</configuration>

When both hello.js and web.config above are saved in the ‘node’ virtual directory in IIS, one can navigate to the node.js application using the following URL:

http://localhost/node/hello.js

As expected, IIS will realize the hello.js file maps to the iisnode handler and invoke it, and as expected a few million CPU cycles later a ‘Hello, world’ is sent back to the client.

However, when a subordinate URL path is requested, IIS returns an error, e.g:

image

The reason for this is that IIS does not understand that paths subordinate to the ‘hello.js’ component of the path should all be handled by the hello.js application. This is unacceptable for all but the most simplistic node.js applications, which typically own the entire URL space. Fortunately, it is easily remedied with the URL rewriting module.

URL rewriting module to the rescue

Fixing this problem requires configuring the URL rewriting module to indicate that the section of the request path that is subordinate to the hello.js component should be handled by the handler for the hello.js component itself. From IIS perspective the request processing occurs as if the request was made for http://localhost/node/helloworld/hello.js, but the original URL path is preserved and available for the handler to act on. URL rewriting is specified in the web.config file as follows (lines 17-24):

   1: <configuration>
   2:   <system.webServer>
   3:     <!-- indicates that the hello.js file is a node.js application 
   4:     to be handled by the iisnode module -->
   5:     <handlers>
   6:       <add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
   7:     </handlers>
   8:     <!-- use URL rewriting to redirect the entire branch of the URL namespace
   9:     to hello.js node.js application; for example, the following URLs will 
  10:     all be handled by hello.js:
  11:     
  12:         http://localhost/node/urlrewrite/hello
  13:         http://localhost/node/urlrewrite/hello/foo
  14:         http://localhost/node/urlrewrite/hello/foo/bar/baz?param=bat
  15:         
  16:     -->    
  17:     <rewrite>
  18:       <rules>
  19:         <rule name="hello">
  20:           <match url="hello/*" />
  21:           <action type="Rewrite" url="hello.js" />
  22:         </rule>
  23:       </rules>
  24:     </rewrite>
  25:   </system.webServer>
  26: </configuration>

The configuration above will not only cause all URLs subordinate to hello.js to handled by hello.js node application; it also allows the hello.js file name to be completely removed from the URL path. With the configuration above the node.js service can now be accessed using any of the following URLs:

http://localhost/node/hello/foo/bar/baz
http://localhost/node/hello/1/2/3
http://localhost/node/hello/f/b/b?param=bat
...

What request URL does the node.js application see?

The request URL passed by IIS to the node.js application is the original URL from before re-writing. For example:

image

Where do I get iisnode again?

Everything you need to get started is at https://github.com/tjanczuk/iisnode. Make sure to check out the urlrewrite sample. Feedback welcome!

7 comments:

  1. This is pretty cool. Since NodeJS is living in IIS, do we get Windows Authentication for free?

    ReplyDelete
  2. Yes, you will get windows authentication as well as all the other IIS modules for free.

    ReplyDelete
  3. This is awesome. Thanks for the information. I ended up having to search for the url rewrite module for IIS on Windows 7, download and install it. Good bye to using ubuntu and a vm :)

    ReplyDelete
  4. I've got a question relating to URL Rewrite.

    Right now my nodejs program handles URL in the form:
    http://localhost/index

    Where "/index" is what my .js program sees as the "pathname", using the built-in url.parse() function. All functions are called from a single .js file.

    How would I set up URL Rewrite to simulate this? I would like my .js file to handle everything coming in on this machine. I don't want it to receive "/node/urlrewrite/etc/pararm

    I'm sure this is an easy URL Rewrite exercise, but I'm new to it.

    Thanks!

    ReplyDelete
  5. I have a question? Can you provide an iisnode JavaScript code example to get the windows user name from an authenticated user - assuming I have IIS set for windows authentication only.

    thank you

    ReplyDelete
  6. There is currently (v0.1.9) no way to extract the name of the Windows authenticated user from a node.js application running in iisnode. I've added https://github.com/tjanczuk/iisnode/issues/87 to address this issue.

    ReplyDelete
  7. Tomasz, tell me please how context collected by modules through the pipeline is going to be passed to iisnode?
    I see now huge problem with using Authentication and Authorization modules as well as with other which write something into context...

    ReplyDelete

About Me

My Photo
I am helping to develop and ship software for Microsoft. My current focus is node.js, JavaScript, and Azure. Before that I worked on .NET Framework and Silverlight, in particular web service technologies: Windows Communication Foundation (WCF), SOAP, WS-*, REST, AJAX.

Search This Blog

Loading...

Blog Archive