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

Hero Image

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):

 <configuration>
   <system.webServer>
     <!-- indicates that the hello.js file is a node.js application 
     to be handled by the iisnode module -->
     <handlers>
       <add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
     </handlers>
     <!-- use URL rewriting to redirect the entire branch of the URL namespace
     to hello.js node.js application; for example, the following URLs will 
     all be handled by hello.js:
     
         http://localhost/node/urlrewrite/hello
         http://localhost/node/urlrewrite/hello/foo
         http://localhost/node/urlrewrite/hello/foo/bar/baz?param=bat
         
     -->    
     <rewrite>
       <rules>
         <rule name="hello">
           <match url="hello/*" />
           <action type="Rewrite" url="hello.js" />
         </rule>
       </rules>
     </rewrite>
   </system.webServer>
 </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!


ArrowPrevious
NextArrow

Most Recent

24 January 2022
Run Node.js from Google Sheets

Import data from any API or data source to Google Sheets using Node.js, NPM, and Fusebit Connectors.

21 January 2022
Linear and Discord Slash Commands

Learn how to build an interactive Slash Command for a Discord bot that lets users create a new issue in Linear.

19 January 2022
Add Slash Commands to Your Discord Bot!

Slash Commands are an extremely powerful way to provide rich interactivity for members of your Discord server, all you have to do is type “/” and you're ready to use your favorite bot.