Search code examples
node.jsweb-configazure-web-app-service

Custom static error page with node and Azure WebApp


I'm building a mix of static pages and node website using Azure WebApps and I'd like to have a custom 404 page and I just can't make it work. Most of the website is static but I have a couple of routes that require server code. My web.config looks as follows:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.webServer>      
        <httpProtocol>
            <customHeaders>
                <remove name="X-Powered-By"/>
                <add name="x-dns-prefetch-control" value="on"/>
            </customHeaders>
        </httpProtocol>     
        <handlers>      
            <add name="iisnode" path="src/server/index.js" verb="*" modules="iisnode"/>
        </handlers>
        <rewrite>
            <rules>
            <rule name="static">
                <match url="(?!dynamicroute).*$" ignoreCase="true"/>
                <action type="Rewrite" url="dist{REQUEST_URI}"/>
            </rule>
            <rule name="dynamic">
                <match url="(?:dynamicroute)(.*)$" ignoreCase="true"/>
                <conditions>
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
                </conditions>
                <action type="Rewrite" url="src/server/index.js"/>
            </rule>
            </rules>            
        </rewrite>
        <!-- Make sure error responses are left untouched -->
        <!--<httpErrors existingResponse="PassThrough"/>-->
        <httpErrors errorMode="Custom" defaultResponseMode="File" existingResponse="PassThrough">   
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" path="~/404.html" responseMode="File" />
        </httpErrors>
    </system.webServer>
</configuration>

I've tried with different variations of httpErrors, value of path, responseMode, removing existingResponse="PassThrough", etc. but I just can't make it work.

Accessing directly /404.html works. The server returns a 404 error when accessing a url that doesn't exist, just not the custom one I want. What am I doing wrong?

I know I could handle everything from nodeland but I'd like to avoid that if possible.


Solution

  • I am able to get the custom 404.html page working with the following web.config file and an expressjs app on Azure App Service. You can take it as reference.

    web.config

    <?xml version="1.0" encoding="utf-8"?>
    
    <configuration>
         <system.webServer>
              <!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
              <webSocket enabled="false" />
              <handlers>
                   <!-- Indicates that the app.js file is a node.js site to be handled by the iisnode module -->
                   <add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
              </handlers>
              <rewrite>
                   <rules>
                        <!-- Do not interfere with requests for node-inspector debugging -->
                        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">                    
                            <match url="^app.js\/debug[\/]?" />
                        </rule>
    
                        <!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
                        <rule name="StaticContent">
                             <action type="Rewrite" url="public{REQUEST_URI}"/>
                        </rule>
    
                        <!-- All other URLs are mapped to the node.js site entry point -->
                        <rule name="DynamicContent">
                             <conditions>
                                  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
                             </conditions>
                             <action type="Rewrite" url="app.js"/>
                        </rule>
                   </rules>
              </rewrite>
    
              <!-- bin directory has no special meaning in node.js and apps can be placed in it -->
              <security>
                   <requestFiltering>
                        <hiddenSegments>
                             <remove segment="bin"/>
                        </hiddenSegments>
                   </requestFiltering>
              </security>
    
              <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
                  <remove statusCode="404" subStatusCode="-1" />
                  <error statusCode="404" path="/public/404.html" responseMode="ExecuteURL" />
              </httpErrors>
    
              <iisnode watchedFiles="web.config;*.js" debuggingEnabled="false" />
         </system.webServer>
    </configuration>
    

    folder structure

    enter image description here

    When I visit any file not exists I got 404 page displayed.

    enter image description here