2
votes

I am trying to enable http to https redirection in our Azure App Service using web.config rewrite rules. According to all documentation I can find, web config redirect using rewrite rules is the official way to get this feature. One of the features that I like and want to support is gzip as an Accepted-Encoding, this is enabled be default. But those two features seem to conflict. Is there another way to do the redirect? Do I have to disable compression?

Here is my redirect rule:

<rule name="Redirect to https" stopProcessing="true">
    <match url="(.*)"/>
    <conditions logicalGrouping="MatchAny">
        <add input="{HTTPS}" pattern="Off"/>
    </conditions>
    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" appendQueryString="true" />
</rule>

Curl command that responds with the content that I only want to be delivered over SSL:

curl "http://[MyUrl]/" -H "Accept-Encoding: gzip, deflate" --compressed

Curl command that executes as expected:

curl "http://[MyUrl]/"

Response:

HTTP/1.1 301 Moved Permanently
Content-Length: 154
Content-Type: text/html; charset=UTF-8
Location: https://[MyUrl]/
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Date: Tue, 29 Aug 2017 19:29:29 GMT

Thanks in advance.

In case this is valuable, requests outside of the root url seem to work as expected. Only the root url seems to return the content without the redirect.

Update
I think this might have to do with my SPA rewrite rule, although I am not sure of the interference as the first rule has stopProcessing on it. I was able to recreate the issue at cdwredirecttest.azurewebsites.net. If you hit the site, it will redirect you to https, but only the first time. Open another browser and try again, this time it will load the site over http. After the server caches the gzip response you no longer get redirected. Here is my full web.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Redirect to https" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="true" />
                    <conditions logicalGrouping="MatchAny">
                        <add input="{HTTPS}" pattern="Off" ignoreCase="true"/>
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" appendQueryString="true" />
                </rule>
                <rule name="Redirect all requests">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
                    </conditions>
                    <action type="Rewrite" url="index.html" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>
2

2 Answers

0
votes

According to your description, I followed your URL rewrite rule and tested on my azure web app. I specified the -L option in order to enable curl to follow HTTP redirects as follows:

curl "http://{your-webapp}.azurewebsites.net/" -L -H "Accept-Encoding: gzip, deflate" --compressed -v

curl "http://{your-webapp}.azurewebsites.net/home/index" -L -H "Accept-Encoding: gzip, deflate" --compressed -v

I could retrieved the response with the Content-Encoding: gzip header from the above commands as follows:

enter image description here

enter image description here

0
votes

After digging around and recreating the issue, I opened a ticket with Microsoft. The issue is specifically around Single Page Applications and SSL redirecting using rewrite rules when compressed content is accepted. Apparently IIS is caching the gzip response so the SSL redirection never occurs. The solution is to disable caching:

<system.webServer>
    ...
    <caching enabled="false" enableKernelCache="false"/>
    ...
</system.webServer>

These are the steps that I came up with to recreate the issue:

  1. Create a new Azure App Service
  2. Rename hostingstart.html to index.html (probably not necessary except the rewrite rule later uses it)
  3. Add the following web.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.webServer>
            <rewrite>
                <rules>
                    <rule name="Redirect to HTTPS" stopProcessing="true">
                        <match url="^(.*)$" ignoreCase="true" />
                        <conditions logicalGrouping="MatchAny">
                            <add input="{HTTPS}" pattern="Off" ignoreCase="true"/>
                        </conditions>
                        <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" appendQueryString="true" />
                    </rule>
                    <rule name="Single Page App">
                        <match url="^(.*)$" ignoreCase="false" />
                        <conditions logicalGrouping="MatchAll">
                            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
                        </conditions>
                        <action type="Rewrite" url="index.html" appendQueryString="true" />
                    </rule>
                </rules>
            </rewrite>
        </system.webServer>
    </configuration>
    
  4. Load the http site in a curl. This will cause the redirect response to happen as expected.

    curl "http://cdwredirecttest.azurewebsites.net" -H "Accept-Encoding: gzip, deflate" --compressed
    
  5. Load the https site in curl. You will get the page content as expected (I believe IIS is caching this gzip response and using it later).

    curl "https://cdwredirecttest.azurewebsites.net" -H "Accept-Encoding: gzip, deflate" --compressed
    
  6. Load the http site in a curl. If you get a redirect response, you will need to repeat 5 and 6. Eventually the response will return the content.

    curl "http://cdwredirecttest.azurewebsites.net" -H "Accept-Encoding: gzip, deflate" --compressed
    
  7. Now load a web browser that has not cached the redirect response. You will load the site over http instead of redirecting to https.

  8. As soon as IIS gives up the cached response, you can use curl to see the redirect and you can repeat 5 and 6 to get the app into the failing state again.