How do I use URL rewriting in combination with mod_jk / mod_proxy / mod_cluster ?

Solution Verified - Updated -

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