How do I use URL rewriting in combination with mod_jk / mod_proxy / mod_cluster ?
Environment
- Apache httpd 2.x
- mod_jk 1.2.x
Issue
- How do I use URL rewriting in combination with mod_jk?
Resolution
mod_jk
Rewrite the URL with the "Passthrough" flag to preserve the URL for the client but present the proper URL to the backend. For example, the following in httpd.conf
RewriteEngine On
RewriteRule ^/app1/jmx-console/(.*)$ /jmx-console/$1 [PT]
And the following in uriworkermap.properties
/jmx-console=loadbalancer
/jmx-console/*=loadbalancer
This will rewrite http://localhost/app1/jmx-console/ to http://localhost/jmx-console/ where it will be handled by mod_jk and delivered to the backend.
For a more powerful rewriting scheme and for rewriting urls and mapping them directly to workers without needing to use JkMount see the following configuration:
worker.list=loadbalancer,status
worker.template.port=8009
worker.template.type=ajp13
worker.template.ping_mode=A
worker.template.socket_connect_timeout=10000
worker.template.connection_pool_timeout=600
worker.node1.reference=worker.template
worker.node1.host=192.168.1.1
worker.node2.reference=worker.template
worker.node2.host=192.168.1.2
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=True
worker.status.type=status
httpd.conf (Make sure mod_rewrite and mod_jk are loaded):
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkShmFile run/jk.shm
RewriteEngine On
RewriteLog logs/mod_rewrite.log
RewriteLogLevel 9
RewriteCond %{QUERY_STRING} ^service=([a-z0-9]*)$
RewriteRule ^/examples$ /examples [E=JK_WORKER_NAME:%1,PT]
<Location /examples>
SetHandler jakarta-servlet
</Location>
<Location /jkstatus>
JkMount status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
With this example you can dynamically map a url to a worker based on the query string, ex http://localhost/examples?service=node1 will go to worker node1 and http://localhost/examples?service=node2 to worker node2.
The following example is slightly more static but matches based on the host then maps to a specific worker.
RewriteEngine On
SetHandler jakarta-servlet
RewriteCond %{HTTP_HOST} vhost1.redhat.com
RewriteRule ^/webapp1/(.*)$ /$1 [E=JK_WORKER_NAME:node1,PT]
RewriteCond %{HTTP_HOST} vhost2.redhat.com
RewriteRule ^/webapp2/(.*)$ /$1 [E=JK_WORKER_NAME:node2,PT]
The above will take requests from webapp1 and automatically map those requests to the root context to be handled by the node1 worker. This is powerful in the sense that any number of arbitrary URLs can be automatically mapped in the main configuration or individual Virtual Hosts to any other URL and handled by a specific mod_jk worker. The SetHandler jakarta-servlet dictates that mod_jk should handle the requests where this is set.
Note It is required to add +ForwardURIProxy to the JkOptions for the above to work correctly. An example JkOptions line would be
JkOptions +ForwardKeySize +ForwardURICompatUnparsed -ForwardDirectories +ForwardURIProxy
mod_proxy / mod_cluster
With mod_proxy and mod_cluster you will want to rewrite your rules and target the balancer or cluster defined in your configuration. For example the default cluster name for mod_cluster is mycluster, so therefore you would have create rewrite rules such as:
RewriteEngine On
RewriteRule ^/app1/jmx-console/(.*)$ balancer://mycluster/jmx-console/$1 [P,L]
When creating RewriteRule(s) in separate VirtualHosts make sure to set CreateBalancers to 0 in the main mod-cluster VirtualHost. Per the documentation:
(CreateBalancers: Define how the balancer are created in the httpd VirtualHosts, this is to allow directives like:)
ProxyPass / balancer://mycluster1/
(0: Create in all VirtualHosts defined in httpd.)
(1: Don't create balancers (requires at least one ProxyPass/ProxyPassMatch to define the balancer names).)
(2: Create only the main server.)
(Default: 2)(Note:) (When using 1 don't forget to configure the balancer in the ProxyPass directive, because the default is empty stickysession and nofailover=Off and the values received via the MCMP CONFIG message are ignored.)
Note: If you wish to create multiple mod_cluster balancers to rewrite to, the balancer names are defined in the mod_cluster configuration on the JBoss side, not the httpd side. For example you could have jboss1 and jboss2 defined with mycluster1 and jboss3 and jboss4 defined with mycluster2 then rewrite to either balancer://mycluster1 or balancer://mycluster2
Note: There is a bug in the EAP 5.1.0 release of mod_cluster that impacts rewrite, please see: https://issues.jboss.org/browse/MODCLUSTER-213 This bug will be fixed in the EAP 5.1.1 release of mod_cluster. As a work-around, using [P] rather than [PT] is an option if you do not need the resulting URLs process by Alias and similar declarations
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments