Skip to content

IIS URL Rewrite: redirects that do not loop

Verified 2 min read

Install URL Rewrite, write HTTP-to-HTTPS and canonical-host rules, understand rule order and stopProcessing, and test 301s without breaking a reverse proxy.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Task

URL Rewrite is an IIS extension, not a built-in role service. It rewrites or redirects a request based on rules in web.config.

Use it for:

  • HTTP → HTTPS redirect;
  • www ↔ apex canonical host;
  • removing trailing slashes or legacy paths;
  • short, deterministic URL mappings.

Do not use it as a reverse proxy. Proxying is ARR; rewriting changes the URL IIS serves, proxying forwards the request to another server.

Download the x64 URL Rewrite module from Microsoft, install, then:

Terminal window
Get-WebGlobalModule -Name RewriteModule

If it is absent, the rules below are ignored or the site returns 500.19 “module not found”.

<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect"
url="https://{HTTP_HOST}/{R:1}"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
  • {R:1} is the captured path from (.*).
  • redirectType="Permanent" sends 301; use Found (302) while testing.
  • stopProcessing="true" stops later rules for this request.

Test:

Terminal window
curl.exe -I http://lab.local/
curl.exe -I https://lab.local/

The first should return 301 with a Location: https://...; the second should return 200 and must not redirect again.

<rule name="Canonical host" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.example\.com$" />
</conditions>
<action type="Redirect" url="https://example.com/{R:1}" redirectType="Permanent" />
</rule>

Put the canonical-host rule before generic path rules. A rule that redirects everything to https://example.com can also catch the health-check path and create a loop if the proxy rewrites Host.

Behind ARR/Nginx, IIS may see HTTP even when the client used HTTPS. A naive {HTTPS} = OFF rule then redirects forever.

Fix the trust boundary first:

  • terminate TLS at the proxy and forward X-Forwarded-Proto;
  • configure ARR to preserve the host/proto;
  • only then add a condition for the forwarded header, or exclude the proxy’s health-check path.

Do not “fix” a loop by disabling the HTTPS redirect for all traffic.

  • Rules run top to bottom; stopProcessing stops the chain.
  • A rule in the site root web.config inherits into applications; a child can clear or override.
  • Conditions are ANDed; multiple <add> entries all must match.
  • {HTTP_HOST} includes the port in some cases; use {HTTP_HOST} carefully with non-default ports.
Terminal window
Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' `
-Filter 'system.webServer/rewrite/rules' -Name '.'

Keep a copy of the previous web.config, test with curl -I, and remove the rule if the redirect chain is wrong. URL Rewrite does not replace a backup of the site configuration.

This page is E1: the lab captured IIS bindings and app pools on Windows 11, but did not install URL Rewrite or test HTTPS redirects. The XML is a starting point; validate it on the target Server 2025 build.

Sources