I am attempting to configure Apache to treat certain endpoints of an application differently.
I need /api, /appname and /admin to forward to separate Tomcat instances on the same host, obviously operating on different ports.
Apache is listening on 443 (SSL).
Looking through Apache's docs I see examples where mod_rewrite is used for similar tasks, but not for this actual use-case.
Only ports 80 and 443 (80 is redirected to 443) are open to the outside, so the others are internal only... let's call them 2001, 3001 and 4001.
EDIT: ADDENDUM: I am using apache 2.2, without plans to update to 2.4.x at this time.
First off, you'll need to make sure that mod_proxy
is enabled. Then, assuming that you want each of /api/
, /appname/
, and /admin/
to look like a subdirectory to the enduser and that they are listening on 2001
, 3001
, and 4001
respectively, I think what you are looking for is something like this:
(in the server or vhost config)
RewriteRule ^/api/(.*) http://localhost:2001/$1 [P,L,QSA]
ProxyPassReverse /api/ http://localhost:2001/
RewriteRule ^/appname/(.*) http://localhost:3001/$1 [P,L,QSA]
ProxyPassReverse /appname/ http://localhost:3001/
RewriteRule ^/admin/(.*) http://localhost:4001/$1 [P,L,QSA]
ProxyPassReverse /admin/ http://localhost:4001/
(in the .htaccess config ...no leading slash ...and no mod_proxy
)
RewriteRule ^api/(.*) http://localhost:2001/otherpath/$1 [P,L,QSA]
RewriteRule ^appname/(.*) http://localhost:3001/otherpath/$1 [P,L,QSA]
RewriteRule ^admin/(.*) http://localhost:4001/otherpath/$1 [P,L,QSA]
The $1
represents what was captured the by the parens. P
tells mod_rewrite to use mod_proxy to handle this rewrite. L
means to make this the last rule; to stop rewriting after this is applied. QSA
appends the query string from the inbound request onto the rewritten request.
The ProxyPassReverse
is used to catch any redirects from the internal instance and rewrite it to match the external URI. NB: mod_proxy
needs to be in the server config (server, vhost, directory) and is not valid in .htaccess
Some helpful refs:
Now, with all that said, you'll probably not want to use mod_rewrite
to do this anyway. It really is mod_proxy
that is doing all the work for you. If you don't have any actual rewriting, you should be using mod_proxy
directly. Even mod_rewrite
just hands it off to mod_proxy
anyway.
From http://httpd.apache.org/docs/2.2/rewrite/avoid.html:
RewriteRule
provides the[P]
flag to pass rewritten URIs throughmod_proxy
.RewriteRule ^/?images(.*) http://imageserver.local/images$1 [P]
However, in many cases, when there is no actual pattern matching needed, as in the example shown above, the
ProxyPass
directive is a better choice. The example here could be rendered as:ProxyPass /images/ http://imageserver.local/images/
Note that whether you use
RewriteRule
orProxyPass
, you'll still need to use theProxyPassReverse
directive to catch redirects issued from the back-end server:ProxyPassReverse /images/ http://imageserver.local/images/
You may need to use RewriteRule instead when there are other RewriteRules in effect in the same scope, as a RewriteRule will usually take effect before a ProxyPass, and so may preempt what you're trying to accomplish.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With