Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Apache to forward endpoints to different ports on the same host

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.

like image 319
Chris Giddings Avatar asked Mar 14 '23 12:03

Chris Giddings


1 Answers

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:

  • http://httpd.apache.org/docs/2.2/rewrite/proxy.html
  • http://httpd.apache.org/docs/2.2/rewrite/remapping.html

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 through mod_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 or ProxyPass, you'll still need to use the ProxyPassReverse 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.

like image 160
Karl Wilbur Avatar answered Apr 06 '23 07:04

Karl Wilbur