Update: The following doesn't completely work: some of the Javascript is problematic, and the logout redirect is broken.
Options:
- Host TeamCity in a Tomcat installation that's listening to
/teamcity; then there'll be no need for outbound rules. I've got this working for a drupal installation.
- Redirect
teamcity.example.com instead (no virtual directory). There are example steps for this elsewhere. This will require some DNS CNAMEs and a wildcard certificate (if using HTTPS for external access).
I'll leave the other instructions here for posterity...
You can configure URL Rewrite to rewrite any part of the text, by setting filterByTags="None".
So I now have the following in C:\Inetpub\wwwroot\web.config:
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Anything to http://www.example.com/teamcity/ should be
rewritten to http://teamcity:81/ -->
<rule name="TeamCity (/teamcity)">
<match url="^teamcity/(.*)" />
<serverVariables>
<!-- URL Rewrite can't deal with Encoding: gzip; turn that off. -->
<set name="HTTP_ACCEPT_ENCODING" value="" />
</serverVariables>
<action type="Rewrite"
url="http://teamcity:81/{R:1}" />
</rule>
</rules>
That's the inbound rule; there are three outbound rules:
<outboundRules>
Login redirects:
<!-- 302 Redirects (for the login page, e.g.) need to be rewritten. -->
<rule name="Teamcity (/teamcity) - Redirect" preCondition="IsRedirect">
<match serverVariable="RESPONSE_LOCATION"
pattern="http://[^/]+/(.*)" />
<action type="Rewrite"
value="http://www.example.com/teamcity/{R:1}" />
</rule>
Normal HTML rewriting:
<!-- Links in HTML need to be rewritten. -->
<rule name="TeamCity (/teamcity) - HTML" preCondition="IsHTML">
<!-- I've ellided the other tag types here; you might want them. -->
<match filterByTags="A, ..."
pattern="^(.*)" />
<action type="Rewrite"
value="http://www.example.com/teamcity/{R:1}" />
</rule>
@import of CSS files:
<!-- TeamCity uses @import for styles; fix that. -->
<rule name="TeamCity (/teamcity) - Style" preCondition="IsHTML">
<match filterByTags="None" pattern="@import "/" />
<action type="Rewrite" value="@import "/teamcity/" />
</rule>
And some pre-conditions:
<preConditions>
<preCondition name="IsRedirect">
<add input="{RESPONSE_STATUS}" pattern="302" />
</preCondition>
<preCondition name="IsHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
It appears to work, but I'll come back and update this answer if I find anything else.