IIS URL Rewrite: redirects that do not loop
Install URL Rewrite, write HTTP-to-HTTPS and canonical-host rules, understand rule order and stopProcessing, and test 301s without breaking a reverse proxy.
- Build
- 26100.33650
- Edition
- Standard / Datacenter
- Architecture
- x64
- Support
- Documentation (E1)
- Evidence
- E1Official documentation
- Verified
- 2026-10-29
- Page type
- Task
The short answer
Section titled “The short answer”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.
Install and verify
Section titled “Install and verify”Download the x64 URL Rewrite module from Microsoft, install, then:
Get-WebGlobalModule -Name RewriteModuleIf it is absent, the rules below are ignored or the site returns 500.19 “module not found”.
HTTP → HTTPS
Section titled “HTTP → HTTPS”<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; useFound(302) while testing.stopProcessing="true"stops later rules for this request.
Test:
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.
Canonical host
Section titled “Canonical host”<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.
Reverse proxy loops
Section titled “Reverse proxy loops”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.
Rule order and scope
Section titled “Rule order and scope”- Rules run top to bottom;
stopProcessingstops the chain. - A rule in the site root
web.configinherits 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.
Verify and roll back
Section titled “Verify and roll back”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.
Lab boundary
Section titled “Lab boundary”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.