When going through a proxy server (A), any self-referential links sent from the apps server (B) need to be re-written to use the proxy as a host instead.

Here's an example:

Response from (B) contains: <code><a href="http://<b>apps</b>/path">path</a></code>
Proxy (A) needs to rewrite as: <code><a href="http://<b>proxy</b>/path">path</a></code>

Normally, this is done by creating an outbound rule that inspects html responses for tags that contain urls, looks for references to to the apps server, and rewrites them.

Here's a normal rule <sup>GUI version</sup>:

<!-- language: lang-xml -->
<outboundRules>
    <rule name="Outbound Links" preCondition="IsHTML" enabled="true">
        <match filterByTags="A, Form, IFrame, Img, Input, Link, Script" pattern="(https?:\/\/proxy|^)\/(.*)" />
        <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
        <action type="Rewrite" value="http://apps/{R:2}" />
    </rule>

Where IsHTML is defined as:

<!-- language: lang-xml -->
<preConditions>
    <preCondition name="IsHTML">
        <add input="{RESPONSE_CONTENT_TYPE}" pattern="text\/html" />
    </preCondition>

The problem is that some of the page content is returned via an XHR request. Minimally, this fails the HTML precondition.

Content Type - text/html vs XHR

but I can expand the rule to also include content types of xhr

However, URL Rewrite still has trouble parsing the returned text into tags because it is not valid HTML.

Here's an example of what the response looks like:

<!-- language: lang-http -->
|6383|updatePanel|ctl00_mainContentPlaceHolder_contentUpdatePanel|

<div id="ctl00_mainContentPlaceHolder_resultsPanel">
   <a href="http://apps/path">path</a>   
</div>

...

|0|hiddenField|__EVENTTARGET||0|hiddenField|__EVENTARGUMENT||0|hiddenField|

However, when I do this, I get the error:

Sys.WebForms.PageRequestManagerParserErrorException:
The message received from the server could not be parsed.

You cannot modify XHR requests coming back from the ASP.NET. Doing so would be to attempt a Man In The Middle Attack (which your proxy is acting as), but Microsoft has good reason to prevent.

Here's a dummy message to explore the syntax ASP.NET uses in the response:

1|#||2|52|updatePanel|ctl00_mainContentPlaceHolder_firstUpdatePanel|
    <p> New Content For First Update Panel </p>

The header starts with 1|#| | and then the number of updates in the rest of the message (2)
Then each update section follows the pattern:

|char_len|update_type|id_of_field_to_update|   
New contents to insert into field

The len in each section must exactly equal the number of characters to follow. So finding and replacing content in these messages is extremely fickle.

The best recommendation is to simply return a relative URL that is server agnostic so the client can be redirected relative to their current domain.