Here is the rule that performs redirect you are asking for:
<rewrite>
<rules>
<rule name="Test Rule" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^((.+.)?)example.com" />
</conditions>
<action type="Redirect" url="http://{C:1}localhost:4000{REQUEST_URI}" appendQueryString="false" />
</rule>
</rules>
</rewrite>
It's pretty straightforward:
<match url=".*" />
matches any URL. Whether requested URL is in example.com
domain is checked in later condition. match
section is useless for our case because it operates with the URL part without a hostname (after first '/').
Condition <add input="{HTTP_HOST}" pattern="^((.+.)?)example.com" />
matches domains like xyz.example.com
or example.com
. If condition is matched, capture group {C:1}
will contain xyz.
for xyz.example.com
and empty string for example.com
, which will be used further.
<action type="Redirect" url="http://{C:1}localhost:4000{REQUEST_URI}" appendQueryString="false" />
The result URL is built as http://{C:1}localhost:4000{REQUEST_URI}
. {C:1}
will hold subdomain name as said above and {REQUEST_URI}
contains URL part after hostname. We also set appendQueryString
to false
because query is a part of {REQUEST_URI}
.
You should add this <rewrite>
section to site web.config
under <system.webServer>
. You could also configure it manually from IIS Configuration Manager. Here is a screenshot of such configuration:
Finally, here is a set of test that demonstrates how urls are changed:
[TestCase("http://xyz.example.com", "http://xyz.localhost:4000/")]
[TestCase("http://xyz.example.com/some/inner/path", "http://xyz.localhost:4000/some/inner/path")]
[TestCase("http://xyz.example.com/some/inner/path?param1=value1¶m2=value2", "http://xyz.localhost:4000/some/inner/path?param1=value1¶m2=value2")]
[TestCase("http://example.com", "http://localhost:4000/")]
[TestCase("http://example.com/some/inner/path", "http://localhost:4000/some/inner/path")]
[TestCase("http://example.com/some/inner/path?param1=value1¶m2=value2", "http://localhost:4000/some/inner/path?param1=value1¶m2=value2")]
public void CheckUrlRedirect(string originalUrl, string expectedRedirectUrl)
{
using (var httpClient = new HttpClient(new HttpClientHandler {AllowAutoRedirect = false}))
{
var response = httpClient.GetAsync(originalUrl).Result;
Assert.AreEqual(HttpStatusCode.MovedPermanently, response.StatusCode);
var redirectUrl = response.Headers.Location.ToString();
Assert.AreEqual(expectedRedirectUrl, redirectUrl);
}
}