I have several web applications hosted on an AWS server on different ports, e.g.
app1: http://x.x.x.x:8080 app2: http://x.x.x.x:9000 ...
I would like to a proxy in front of these apps (apache, nginix etc.) so that all of them can be accessed using port 80. I could think of two aproaches:
Put each app on a different sub-domain and forward based on the sub-domain, e.g
http://app1.mydomain.com --> http://x.x.x.x:8080 http://app2.mydomain.com --> http://x.x.x.x:9000
However in my case, I do not control the creation of subdomains. I have been given on sub-domain and I have to live with that. So this approach does not work.
Use a seperate URL for each app and then rewrite the URL, e.g.
http://mysubdomain.mydomain.com/app1 --> http://x.x.x.x:8080 http://mysubdomain.mydomain.com/app2 --> http://x.x.x.x:9000
However, I am running into an issue with this approach. For example,
http://mysubdomain.mydomain.com/app1 correctly returns index.html from the app1, but then that index.html asks for js and css files without the app1 prefix, e.g. it asks for
http://mysubdomain.mydomain.com/js/main.js instead of
http://mysubdomain.mydomain.com/app1/js/main.js. As you can see, the forwarding rule no longer works. Even more confusing is that if my initial request terminates with a slash (
http://mysubdomain.mydomain.com/app1/), then the requests for js and css files is formatted correctly (
http://mysubdomain.mydomain.com/app1/js/main.js). I don't understand this behavior!
Is there any other approach that you can think of? I have heard of host header mapping, but couldn't figure out how it works. I can't imagine that this problem has not been solved!
Edits based on suggestion from @stoned
Here's my attempt to reverse proxy this app using Apache running at
# Reverse proxy requests for /app1 to http://x.x.x.x:8080 ProxyRequests off ProxyPass /app1 http://x.x.x.x:8080 ProxyPassReverse /app1 http://x.x.x.x:8080
This does not work when I type
http://www.example.com/app1 in my browser (note no slash at the end).
index.htmlis served correctly
index.htmlasks for css and js with lines like this:
<link rel="stylesheet" href="vendor/bootstrap.min.css"/> <script src="vendor/angular.min.js"></script>
This translates to requests like this with no
app1imbedded in the URL:
Obviously, the reverse proxy does not know what to do with these!
However, if I add a slash at the end of the URL (
http://www.example.com/app1/), then the requests are translated correctly:
I don't understand how adding a slash at the end makes the browser behave differently! Anyway, the important point is that I can't expect my users to type a slash at the end. Any thoughts on how to solve this problem?
Solved - Finally!
After bunch of googling I found that a trailing slash is used to indicate that the requested resource is a directory. In such cases the "default" resource from the directory is returned (usually index.html). If a user wrongly requests a directory without a trailing slash, mod_dir (which is normally loaded in Apache installations) adds a trailing slash and does a client-side redirect, fixing the problem.
In my case,
http://www.example.com/app1 was not redirecting to
http://www.example.com/app1/ (with a trailing slash) because
/app1 is not a real directory on the apache server - mod_dir was not detecting this. Hence this URL was being proxied to http://x.x.x.x:8080 as is. While this was correctly returning the index.html, but the subsequent requests were relative to
http://www.example.com and not
http://www.example.com/app1. To fix the problem, I added a rewrite rule to redirect
http://www.example.com/app1/ (with a slash). I also changed my reverse proxy rules to only match if I find a trailing slash. See below:
# Fix any request for /app1 to /app1/ RewriteEngine on RewriteRule ^/app1$ /app1/ [R] # Reverse proxy requests for /app1/ to http://x.x.x.x:8080/ ProxyRequests off ProxyPass /app1/ http://x.x.x.x:8080/ ProxyPassReverse /app1/ http://x.x.x.x:8080/