Search code examples
azureazure-web-app-serviceiisnode

How to configure web.config for multiple virtual applications in Azure App Service?


I am trying to have multiple Node.js applications working in parallel in the same Azure App Service instance. I tried making a virtual application per Node.js app but I constantly get a server error (code 500). I use ZipDeploy or Azure DevOps to deploy my applications.

I suspect the problem might be that the web.config files associated with my applications is incorrect.

Here are some details on my setup:

In the Application settings menu of my App Service instance, I went to the Virtual applications and directories settings and put the following:

/                         site\wwwroot                        Application x
/mysite1                  site\wwwroot\mysite1                Application x
/mysite2                  site\wwwroot\mysite2                Application x

My wwwroot directory looks as follows. To make sure the problem doesn't come from the code itself, I used the same Node.js application for all three:

index.html
server.js
scripts
web.config (*)
----- mysite1
      |----- index.html
      |----- server.js
      |----- scripts
      |----- web.config (**)
----- mysite2
      |----- index.html
      |----- server.js
      |----- scripts
      |----- web.config (***)

I use the default web.config file (provided by Kudu) for the three of them:

<?xml version="1.0" encoding="utf-8"?>

<configuration>
  <system.webServer>

    <webSocket enabled="false" />
    <handlers>
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^server.js\/debug[\/]?" />
        </rule>

        <rule name="StaticContent">
          <action type="Rewrite" url="public{REQUEST_URI}"/>
        </rule>

        <rule name="DynamicContent">
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="server.js"/>
        </rule>
      </rules>
    </rewrite>

    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin"/>
        </hiddenSegments>
      </requestFiltering>
    </security>

    <httpErrors existingResponse="PassThrough" />

  </system.webServer>
</configuration>

Using this configuration, I can reach https://myappservice.azurewebsites.net/ without issue but https://myappservice.azurewebsites.net/mysite1 only returns a server error.

I tried taking off the handlers from the web.config files in subdirectories (** and ***) as instructed in similar questions but to no avail.

What is the correct configuration for these three files? I suppose the rewrite rules need to be adjusted but I am unsure what is the exact expected value for each.


Solution

  • I finally managed to pinpoint the exact problem through the IIS logs (/LogFiles/W3SVC.../ on Kudu) :

    ModuleName="RewriteModule", Notification="SEND_RESPONSE", HttpStatus="500", HttpReason="URL Rewrite Module Error.", HttpSubStatus="52", ErrorCode="Cannot create a file when that file already exists.
     (0x800700b7)", ConfigExceptionInfo="\\?\D:\home\site\wwwroot\mysite1\web.config ( 16) :Cannot add duplicate collection entry of type 'rule' with unique key attribute 'name' set to 'NodeInspector'
    "
    

    What needed to be changed were the handler and rule names in the child web.config file, so that they wouldn't clash with the names in the parent web.config file. Everything works correctly now.