Search code examples
iisurl-rewritingreverse-proxy

IIS Rewrite IP:Port to {domain}/{thing}


What I'm trying to do:

  • I own a domain, let's say blahblahblah.com
  • On the server, it points to :80 and :443 properly - this is working
  • I want to remap so that if a user visits blahblahblah.com/thing1 then it maps to localhost:5000
  • Similarly, I also want to remap so that if a user visits blahblahblah.com/thing2 then it maps to another server and port on my local network (not exposed to the internet)

I essentially want to use my webserver to communicate with other servers on my network and other ports through "sub directories" or whatever they are called in this instance (site/subdir, site2/subdir). I've been trying to solve this issue for days! I've installed ARR (and enabled the Proxy) and the URL Rewrite modules on my IIS.

I've attempted god knows how many different rewrite templates on SO. I can get partial success, in which the route /thingx/ resolves, but all the resources are referencing blahblahblah.com and (appropriately) can't find the resources for the site at that address.

Current rewrite (resolves some resources at blahblahblah.com/thing1, but others are misrouted):

<rewrite>
  <rules>
    <rule name="Thing1" enabled="true">
       <match url="(thing1*)" />
       <action type="Rewrite" url="http://localhost:5000/{R:0}" />
     </rule>
  </rules>
</rewrite>

EDIT: I've updated my rules to the below, as per this article from Microsoft Docs: Reverse Proxy with URL Rewrite v2 and Application Request Routing . These rewrites supposedly do exactly what I need, but the result is not the same in my case, and I still have no clue why.

<rules>
    <rule name="Thing1" enabled="true">
        <match url="^thing1/(.*)" />
        <action type="Rewrite" url="https://localhost:5000/{R:0}" />
    </rule>
</rules>
<outboundRules>
    <rule name="Add application prefix" preCondition="IsHTML">
        <match filterByTags="A" pattern="^/(.*)" />
        <conditions>
            <add input="{URL}" pattern="^/(thing1)/.*" />
        </conditions>
        <action type="Rewrite" value="/{C:1}/{R:1}" />
    </rule>
    <preConditions>
        <preCondition name="IsHTML">
            <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
        </preCondition>
    </preConditions>
</outboundRules> 

More Notes:

  • localhost:5000 works as expected
  • localhost/thing1 resolves in 404 Not Found
  • blahblahblah.com/thing1 resolves in pulling in the default HTML page, but none of the assets (javascript, css, etc), they return 404 Not Found.

EDIT: It may be important to note that these rules have been written into the default site (bound to :80, :443) on IIS' web.config. Writing these rules in C:\Windows\System32\inetsrv\config\applicationHost.config results in a 500.

Any feedback on what I'm doing wrong?


Solution

  • Part of this was due to the way SPAs are handled (# and history mode), but I ended up solving with the below webconfig for IIS, which allows me to nest everything under a /foobar endpoint:

        <rewrite>
          <rules> 
            <rule name="Subdirectory Index" stopProcessing="true">
              <match url="^foobar/index\.html$" ignoreCase="false" />
              <action type="None" />
            </rule>
            <rule name="Subdirectory Routes" stopProcessing="true">
              <match url="." ignoreCase="false" />
              <conditions>
              <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
              <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
              </conditions>
              <action type="Rewrite" url="/foobar/index.html" />
            </rule>
          </rules>
        </rewrite>