Search code examples
asp.netajaxiisurl-rewriting

ARR throws 404 on adx URLs after rewrite


I have a IIS HA setup (2 ARR, 2 IIS) that work fine except for .axd ressources.

When going thru ARR any and all .axd return a 404 but when I bypass the ARR (simple DNS record change), the request returns a 200 as expected. Therefore all AJAX and ReportBuilder elements don't load on the page when going thru ARR.

Capturing traffic and looking at logs (website logs & failed request tracing) shows the URL pretty much the same on either ARR or IIS:

Thru ARR

2023-08-22 16:10:50 192.168.24.5 GET /WebResource.axd d=lq0PviHnSOFiLL9A9_OGEXaQ7vrP7owj6Gsil0FilogN4XCpuO-ZyR0rHKUEu10SOhO7ChgFq7EcMmy0hf-PVMStIfo8U-QYx43ikiPtIVpdwvD60NrAzxZxcyX-bTPZmF1AUOhi6o5gGfj6aur9LD7VZWW7J7XhXLdmtI9kU5k1&t=636692481600000000 443 - 192.168.30.110 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/116.0.0.0+Safari/537.36 https://domainhub.domain.com/QuestAfExtClient 404 0 2 26

Directly IIS

2023-08-22 16:17:30 192.168.24.8 GET /WebResource.axd d=lq0PviHnSOFiLL9A9_OGEXaQ7vrP7owj6Gsil0FilogN4XCpuO-ZyR0rHKUEu10SOhO7ChgFq7EcMmy0hf-PVMStIfo8U-QYx43ikiPtIVpdwvD60NrAzxZxcyX-bTPZmF1AUOhi6o5gGfj6aur9LD7VZWW7J7XhXLdmtI9kU5k1&t=636692481600000000 443 DOMAIN\user 192.168.30.110 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/116.0.0.0+Safari/537.36 https://domainhub.domain.com/QuestAfExtClient 200 0 0 11

I've googled this problem but most solutions are to skip .axd files in URL rewrite module so it gets processed without rewrite but this doesn't work here, I think because the .axd needs to be forwarded to the server farm like the rest.

Any suggestions on getting those axd working thru the ARR?

Here are my URL rewrite rules from ARR applicationHost.config:

<globalRules>
    <clear />
    <rule name="HTTPS Redirection" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
        <match url="*" negate="false" />
        <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
            <add input="{HTTPS}" pattern="off" />
        </conditions>
        <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" />
    </rule>
    <rule name="ARR Route to Farm" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
        <match url="*" />
        <action type="Rewrite" url="https://DomainIIS/{R:0}" appendQueryString="false" />
    </rule>
</globalRules>

And my webFarm config:

<webFarm name="DomainIIS" enabled="true">
    <server address="IIS-01-M.domain.com" enabled="true">
        <applicationRequestRouting weight="100" />
    </server>
    <server address="IIS-02-M.domain.com" enabled="true">
        <applicationRequestRouting weight="1" />
    </server>
    <applicationRequestRouting>
        <protocol includePortInXForwardedFor="false" minResponseBuffer="0">
            <cache enabled="false" queryStringHandling="Preserve" validationInterval="00:00:00" />
        </protocol>
        <healthCheck url="http://iis.domain.com" interval="00:00:05" timeout="00:00:05" statusCodeMatch="200" minServers="1" />
        <affinity useCookie="true" />
        <loadBalancing />
    </applicationRequestRouting>
</webFarm>

All these servers are running IIS 10.0 on Win2019.


Solution

  • Ok I figured it out. Looking at the logs I noticed the query string was being striped from the URL after the route to farm rewrite is done. The 404 is therefore expected for AXD ressources.

    The UI for URL rewrite "route to farm" does not include the "append query string" option like it does for basic "rewrite" option. The option does appear in the applicationHost.config as shown above. However I decided to not modify the config file as it might get overwritten at some point and adjust the rewrite path to /{R:1}?{QUERY_STRING} as a workaround. In context, here is the adjusted rule:

    <rule name="ARR Route to Farm" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
            <match url="*" />
            <action type="Rewrite" url="https://DomainIIS/{R:1}?{QUERY_STRING}" appendQueryString="false" />
    </rule>
    

    Works great now! AJAX and ReportBuilder works fine :)