Apache Reverse Proxy Configuration not Working with Location /#/

George asked:

I am trying to get an apache 2.4 reverse proxy (RHEL 7.7) working with an application that has hard coded paths making my reverse proxy configuration quite challenging. This serverfault link (How to handle relative urls correctly with a reverse proxy) has been great, particularly approach solution #3 of putting in a bunch of locations (which have been hard coded). My proxy runs paths to distinguish applications (www.example.com/app1 and www.example.com/app2). In this example, /app2 has hard-coded a bunch of directories like /static and /api. Putting those Locations with ProxyPass and ProxyPassReverse in has worked great and the site is functional.

However, they have also hard coded /#/ for whatever reason and I see them in href links in certain places. So, I followed the pattern and defined a Location for /#/. However, it doesn’t work. For whatever reason, when I hit that link, it doesn’t direct it to the app2.internal.example.com server, but instead serves my home page that responds at www.example.com/. In the URL, I see it is displaying www.example.com/#/SOMEWHERE, but it is clearly not getting to app2. The config file is below. Is /#/ a special location that can’t be used? Are there any solutions for this? Thanks in advance.

<Location /app2/>
  ProxyPass https://app2.internal.example.com/
  ProxyPassReverse https://app2.internal.example.com/
  Header add referer "https://app2.internal.example.com/"
  RequestHeader set referer "https://app2.internal.example.com/"
</Location>

<Location /static/>
  ProxyPass https://app2.internal.example.com/static/
  ProxyPassReverse https://app2.internal.example.com/static/
  Header add referer "https://app2.internal.example.com/"
  RequestHeader set referer "https://app2.internal.example.com/"
</Location>

<Location /api/>
  ProxyPass https://app2.internal.example.com/api/
  ProxyPassReverse https://app2.internal.example.com/api/
  Header add referer "https://app2.internal.example.com/"
  RequestHeader set referer "https://app2.internal.example.com/"
</Location>

<Location /#/>
  ProxyPass https://app2.internal.example.com/#/
  ProxyPassReverse https://app2.internal.example.com/#/
  Header add referer "https://app2.internal.example.com/"
  RequestHeader set referer "https://app2.internal.example.com/"
</Location>

My answer:


The # in a URL delineates the URL fragment, a part of the URL indicating a location in the document to which the browser will scroll once the document is loaded.

Some JavaScript libraries have abused the URL fragment to pass information around client-side to support various functions of single page apps. This is no longer in vogue (and never was a very good idea) and such applications need to be updated to use the History API and change these URLs appropriately to no longer use fragments. Your developers should do this a few years ago.

There are several reasons this was a bad idea to begin with, but most importantly for your situation, the URL fragment is strictly client side and is never passed to the server. If you have a URL http://www.example.com/#/, the path is /, and that is all the server sees. It never sees the #/ as these are only client side. There is no way in plain HTTP to send it to the server, so you can’t match on it in a Location. Or anything else.


View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.