CFML on Tomcat via Apache AJP Proxy, Redux

I often use Tomcat as my servlet container to power my CFML apps (works great for ColdFusion, Open BlueDragon and Railo!). I've been perfectly happy with the power and flexibility of using Apache HTTPD's mod_rewrite with an AJP proxy, as Sean Corfield has detailed. Then, after repeating a lot of rewrite rules in all of my virtual host definitions, I decided to merely place the following in my main Apache configuration file:

<Proxy *>
Allow from 127.0.0.1
</Proxy>
ProxyPreserveHost On
ProxyPassMatch ^/(.+\.cf[cm])(/.*)?$ ajp://localhost:8009/$1$2

That's it! Now, any Apache virtual hosts for CFML application can be defined as simple as this:

<VirtualHost *:80>
ServerName myrockinapp
DocumentRoot /var/www/myrockinapp
DirectoryIndex index.cfm
</VirtualHost>

I can still easily add URL rewriting to my Apache virtual hosts. For example, when using Mura CMS I often set the properties siteIdInURLs=0 and indexFileInURLs=0 to make super clean looking URLs (with no siteID or index.cfm in the URLs). This then of course requires a rewrite rule to ensure the proper requests are passed to Tomcat, which is as simple as adding these lines to your virtual host (or an .htaccess file in your Web root):

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]

Makes all the configuration I used in this post look a bit silly now :P

Also, if you're interested in a clean, production-worthy server setup running on Ubuntu 10.04 with Railo, Tomcat, Apache and MySQL, I have this fairly well documented in this Google Doc.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Alan Holden's Gravatar This rewrite rule was just what I was looking for to SES the Mura URLS on my OpenBD install. I also had to add this to the web.xml on Matt Woodward's suggestion:
<code>
<servlet-mapping>
<servlet-name>cfmServlet</servlet-name>
<url-pattern>/default/index.cfm/*</url-pattern>
</servlet-mapping>
</code>
Thanks!
# Posted By Alan Holden | 9/1/10 12:45 AM
Todd Rafferty's Gravatar Jamie! Awesome job! That cleans up my httpd.conf nicely - thanks for sharing this!
# Posted By Todd Rafferty | 9/1/10 6:35 AM
Jamie Krug's Gravatar @Alan: Glad to help out! And yes, the servlet mapping is important for Tomcat to handle "search engine safe/friendly" (SES/SEF) URLs that have path_info after a *.cfm. Sean posted a quick summary of this configuration here:
http://corfield.org/entry/Railo_for_Dummies_Part_V...

@Todd: Glad to help! I like me some clean config files too ;-)
# Posted By Jamie Krug | 9/1/10 9:27 AM
Sam's Gravatar thanks Jamie. I have a new install of Mura v5.2.2806 using Linux (Lenny) / Resin (3.1.9) / Apache2 (2.2.9) and mod_caucho.

I get an internal error using the above in an .htaccess (in the vhost webroot)

I think im nearly there. I have settings.ini.cfm set as siteidinurls=0 AND indexfileinurls=0.

Would the above work for Resin?
(end result im wanting is no siteid or index.cfm in the middle of the URL)

Cheers Sam
# Posted By Sam | 9/9/10 4:59 PM
Sam's Gravatar hmmm, fail on my behalf! I needed to a2enmod rewrite and then /etc/init.d/apache2 restart... now working sweetly under the Resinator.
# Posted By Sam | 9/9/10 5:43 PM
Jamie Krug's Gravatar Sam,

I'm glad you figured it out, but yes, probably worth mentioning that these apache mods need be enabled: proxy, proxy_ajp (or proxy_http) and rewrite. In Ubuntu/Debian that's as simple as:

sudo a2enmod proxy_ajp rewrite
sudo service apache2 restart
# Posted By Jamie Krug | 9/9/10 9:17 PM
Sam's Gravatar thanks Jamie. I've read alot of your posts and its great to get such insightful knowledge. (Both categories and subcategories work sweetly too). We're giving Jetty a go now, to see how that fires.

Thank you for generously contributing such a useful blog ... with code that works!
# Posted By Sam | 9/9/10 9:24 PM
Jamie Krug's Gravatar Sam, thanks for the kind words. I like to share when I can. Cheers.
# Posted By Jamie Krug | 9/9/10 9:31 PM
Anuj Gakhar's Gravatar Awesome man! your posts on Railo + Tomcat + Url rewriting have helped me a lot. Thanks a ton dude :)
# Posted By Anuj Gakhar | 12/24/10 8:56 AM
Jamie Krug's Gravatar @Anuj, happy to help. Cheers.
# Posted By Jamie Krug | 12/24/10 3:27 PM
Tim's Gravatar Using Mura and I've added an SSL cert which works great, but doesn't work with the rewrite rules. How would I go about adding https(s) logic to the rewrite.

I came across this code, which greatly simplifies the https redirection, but how would I incorporate it with your solution?

RewriteCond %{SERVER_PORT}s ^(443(s)|[0-9]+s)$
RewriteRule ^(.+)$ - [env=askapache:%2]

# redirect urls with index.html to folder
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+/)*index\.html\ HTTP/
RewriteRule ^(([^/]+/)*)index\.html$ http%{ENV:askapache}://%{HTTP_HOST}/$1 [R=301,L]

I'm definitely a novice with the mod_rewrite.

Thanks,
# Posted By Tim | 1/5/11 1:20 PM
Tim's Gravatar So I've got the http/https rules working, but now it throws the index.cfm back into the URL. Here's the logic:

RewriteCond %{SERVER_PORT}s ^(443(s)|[0-9]+s)$
RewriteRule ^(.+)$ - [env=askapache:%2]

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^([a-zA-Z0-9/-]+)$ http%{ENV:askapache}://%{SERVER_NAME}/index.cfm%{REQUEST_URI} [QSA,L]

After this processes, what can I do to remove the index.cfm?

I tried setting the [OSA,L] to [PT] then added:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^([a-zA-Z0-9/-]+)$ http%{ENV:askapache}://%{SERVER_NAME}/index.cfm%{REQUEST_URI} [QSA,L]

No Luck... Any help would be greatly appreciated...
# Posted By Tim | 1/6/11 1:38 PM
Jamie Krug's Gravatar Tim,

Sorry, I'm not sure exactly what your goal is here. Can you elaborate on what you're trying to accomplish?

FWIW, here's a sample Apache vhost pair (SSL and non-SSL) that works fine for me, with Railo running in Tomcat, and using the basic proxy config in Apache as described above in this post...


<VirtualHost *:80>
   ServerName me.ssl
   DocumentRoot /home/jkrug/www/ssl/www
   DirectoryIndex index.cfm

   RewriteEngine On

   RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
   RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]
</VirtualHost>

<VirtualHost *:443>
   ServerName me.ssl
   DocumentRoot /home/jkrug/www/ssl/www
   DirectoryIndex index.cfm

   SSLEngine on
   SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
   SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

   <FilesMatch "\.(cfc|cfm)$">
      SSLOptions +StdEnvVars
   </FilesMatch>

   RewriteEngine On

   RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
   RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]
</VirtualHost>
# Posted By Jamie Krug | 1/6/11 3:06 PM
Jeff Lucido's Gravatar Thanks for condensing mod_rewrite rules into a simplistic package. I decided to give your example a whirl in place of the rewrite rules I have been using for some time on a new Mura install (OpenCF Summit got me thinking I needed to play with the CMS again). Everything went well, however when I applied the rules to another application I have I am running into issues with URI that use "." delimiters.

Specifically, I have a URL "www.xyzcompany.com/support.faq"; and I get a 404 error from Apache stating the URL is not found on the server. If I change it to "www.xyzcompany.com/index.cfm/support.faq"; it works properly and the page is loaded.

I am not very familiar with mod_rewrite (I should be though) so I think there is a minor tweak needed to the pattern matching to accept URI values with a "." delimiter, right? The problem is I am not too sure how to go about this. Here is an example of a few rewrite rules I used to use in my vhost.conf file which allowed for URI values containing ".":

# If it's a CFML (*.cfc or *.cfm) request, just proxy it to Tomcat:
RewriteRule ^(.+\.cf[cm])(/.*)?$ ajp://%{HTTP_HOST}:8009$1$2 [P]

# If trailing slash and real directory, then append index.cfm and proxy it to Tomcat/OpenBlueDragon:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^(.+/)$ ajp://%{HTTP_HOST}:8009%{REQUEST_URI}index.cfm [P]

# If it's a real file (and we haven't proxied to Tomcat, so it must be static), just serve it:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteRule . - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([a-z]{1}.*)?$ ajp://%{HTTP_HOST}:8009/index.cfm/$1 [QSA,P]

Any thoughts on how to get your simplified mod_rewrite rules to accommodate "." delimited URI values?
# Posted By Jeff Lucido | 2/27/11 9:05 PM
Jamie Krug's Gravatar Jeff,

To allow a period in your path info, you just need to add that character (escaped) to the regex. So, just add "\." before the hyphen:

RewriteRule ^([a-zA-Z0-9/\.-]+)$ /index.cfm%{REQUEST_URI} [PT]

HTH!
# Posted By Jamie Krug | 2/28/11 2:50 PM
Jason's Gravatar Hey Jamie,

Been working the past week or two with your Google doc Ubuntu 10.x/ Tomcat6 / Railo setup on EC2 and so far so good. Wanted to note one piece I ended up adding as most of my Railo access is going over the flashservices/gateway.

After trying a few ways to resolve access to the gateway when connecting via a virtual host or virtual host alias, the solution ended up being the addition of the following to the httpd.conf:

ProxyPassMatch ^/flashservices/gateway(/.*)?$ ajp://localhost:8009/flashservices/gateway/$1$2

So far this seems to work as expected - connections to the flash gateways work and the cfc service paths are particular to the vhost. But my RegEx chops are pretty weak and I just did trial and errorred this based off your examples. Would definitely like to know what your thoughts are on it.

Thanks again for the excellent Google Doc, looking like I am going to end up with just about the setup I had hoped for.

Best,
J
# Posted By Jason | 3/7/11 8:27 PM
Andrew Myers's Gravatar This is just awesome Jamie. Thank you for sharing!
# Posted By Andrew Myers | 4/13/11 9:34 PM
Dave's Gravatar Thank you for sharing. This is awesome and worked perfectly!
# Posted By Dave | 12/8/11 3:21 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002. Contact Blog Owner