Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using URL Rewrite on IIS to set response's Location header

I have .Net application (built with the Outsystems platform) deployed on a Windows 2008R2, IIS 7 environment. This application is already working with no problems. It is serving requests through HTTPS on port 443 and i can access it with no problems.

Now, there is the need to enable some users to access it through a NAT, which is configured to serve requests on port 8200. The requests are forwarded to the server with no problem, except when the response is a redirect (HTTP 302). In these cases, the Location Header of the response is set with the port where the application is actually being served which is port 443. When the client's browser tries to access this URL that was set in the Location Header, it will fail since the NAT is only serving the requests in port 8200.

In sum:

  • Client browser accesses https://myserver:8200/myapp ;
  • NAT translates the URL and forwards to https://myserver:443/myapp ;
  • Application replies with a 302 redirect to https://myserver:443/redirect ;
  • Client browser accesses https://myserver:443/redirect ;
  • NAT blocks this access because it is expecting port 8200 ;

Here is what i tried to do; I installed the URL Rewrite module in IIS and created the following rules:

  • An Inbound rule to store the request's Host Header (in these cases it's https://myserver:8200) to a server variable ORIGINAL_HOST.
  • An Outbound rule to replace the host part of the URL that is sent in the response's Location Header (https://myserver:443/redirect) with the value stored in my server variable ORIGINAL_HOST. The rule is only applied in case of a redirect.

The problem i am facing now is that the minute i enable this Rule, all AJAX requests stop working even it the rule does not apply to them and even when not accessing the application through the NAT. When this happens, i am seeing through IE's Network tab in Developer Tools that the request header and body is ok, response header is ok, but the response body is empty and should not be. Also, if i try to debug the AJAX request at the server using a breakpoint, it is not stopping at the breakpoint.

So, my question: Is using the URL Rewrite the best way to solve the NAT/URL problem? If so, how can i solve the AJAX situation? If not, then how do i solve the redirect problem?

*edit: here is my rule configuration:

  • Inbound rule to store the host value
  • Outbound rule to replace the host
  • Outbound precondition to handle only redirects

Thank you in Advance,

João Gomes

like image 551
João Gomes Avatar asked Jun 27 '14 11:06

João Gomes


1 Answers

The simplest url rewrite to do what you want is an outbound rule targeting 3xx redirects. The rule can parse the location with regex, and allow you to change the port. I'm not sure if this accomplishes everything you are setting out to do (if port must be dynamic) but it should at least get you most the way there.

The pattern (https?://[^:/]+):?([0-9]+)?(.*) will parse the location as follows:

https://sub.host.com:1337/foo/bar?query=true

{R:1} => https://sub.host.com
{R:2} => 1337
{R:3} => /foo/bar?query=true

Note: If the port is not in the URL, {R:2} will be empty.

Then for your use case, it would reassemble in the action rewrite to:

{R:1}:8200{R:3} => https://sub.host.com:8200/foo/bar?query=true

Outbound URL Rewrite


In web.config <system.webServer>:

<rewrite>
    <outboundRules>
        <rule name="Redirect to port" preCondition="3xx Redirect">
            <match serverVariable="RESPONSE_LOCATION" pattern="(https?://[^:/]+):?([0-9]+)?(.*)" />
            <action type="Rewrite" value="{R:1}:8200{R:3}" />
        </rule>
        <preConditions>
            <preCondition name="3xx Redirect">
                <add input="{RESPONSE_STATUS}" pattern="3[0-9][0-9]" />
            </preCondition>
            <preCondition name="3xx redirect no query string">
                <add input="{RESPONSE_LOCATION}" pattern="^(.*)(\?.+)$" negate="true" />
                <add input="{RESPONSE_STATUS}" pattern="3[0-9][0-9]" />
            </preCondition>
            <preCondition name="3xx redirect with query string">
                <add input="{RESPONSE_STATUS}" pattern="3[0-9][0-9]" />
                <add input="{RESPONSE_LOCATION}" pattern="^(.*)(\?.+)$" />
            </preCondition>
        </preConditions>
    </outboundRules>
</rewrite>

@hally9k - maybe this is what you were looking for also?

like image 195
cchamberlain Avatar answered Sep 27 '22 18:09

cchamberlain