March 28, 2009
In the comments on
Part IV, Barney suggested using AJP to proxy and I confirmed that it preserves the CGI variables
REMOTE_ADDR and
REMOTE_HOST which Paul Kukiel asked me about. Paul also noted that adding the
ProxyPreserveHost directive causes the host headers to be passed through the proxy. I'd actually added that locally but didn't want to complicate the blog post by mentioning it.
In this Appendix post, I want to tackle SES URLs. One downside of Tomcat is that it does not support the following common form of SES URLs:
We're going to tackle this by changing our proxy strategy to use
mod_rewrite.
To recap, here's our previous virtual host definition in Apache (with ProxyPreserveHost added):
<VirtualHost *:80> ServerName railo.corfield.org
DocumentRoot /Users/scorfield/Sites
ProxyPreserveHost On
ProxyRequests Off
<Proxy *> Order deny,allow
Allow from all
</Proxy> ProxyPass /
http://localhost:8080/ ProxyPassReverse /
http://localhost:8080/ </VirtualHost> Instead of using the basic
ProxyPass, we're going to use the 'proxy' option of
RewriteRule to rewrite just CFML requests as first step. We need to turn the rewrite engine on and then replace the forward proxying directives with a rewrite rule:
<VirtualHost *:80> ServerName railo.corfield.org
DocumentRoot /Users/scorfield/Sites
ProxyPreserveHost On
ProxyPassReverse /
ajp://localhost:8009/ RewriteEngine On
RewriteRule ^/(.*\.cf[cm])$
ajp://localhost:8009/$1 [P]
</VirtualHost> The rewrite rule says: "Match any complete URL that ends in .cfm or .cfc and send it to Tomcat via AJP". The
[P] flag means "proxy this request and stop processing rules". Don't forget to restart Apache for the change to take effect:
sudo apachectl restart
Now our CFML requests are being processed by Tomcat but everything else is being processed by Apache.
Normally, SES URLs are handled in CFML applications by looking at the CGI variable PATH_INFO and processing that. We can't quite get there but we could arrange for that part of the path to be passed as part of the query string instead. To do that, we add a second rewrite rule that handles URLs where .cfm (or .cfc) is present but not at the end of the URL:
This isn't ideal (because
CGI.PATH_INFO does not contain the information we need) but at least we can now get at it via
URL.PATH_INFO. You can use any name for the URL variable to avoid possible collisions with your own URL variables (but of course whatever you use in the rewrite rule must match what you use in your code!). Unfortunately, you'll have to modify code that relies on
CGI.PATH_INFO to use
URL.PATH_INFO instead, e.g., the SES URL processing in Fusebox 5.5 (around line 66 of
myFusebox.cfc). It's a pity we cannot set CGI variables in CFML because then we could
force CGI.PATH_INFO back to a correct value!
If anyone knows of a better solution, please let me know!
Comments
any advantage to using ajp over what I am doing here? http://www.deliciouscoding.com/post.cfm?entry=5-railo-on-leopard-setting-up-sites-and-editing-server-files
Posted By dave / Posted At
3/30/09 4:33 PM
Sava cms does this with a jar file and then adding the mapping in web.xml
<servlet> <servlet-name>FUServlet</servlet-name> <display-name>FriendlyURLServlet</display-name> <description>Translates friendly URLs to objects</description> <servlet-class>com.blueriver.sava.FriendlyURLServlet</servlet-class> </servlet>
<servlet-mapping> <servlet-name>FUServlet</servlet-name> <url-pattern>/go/*</url-pattern> </servlet-mapping>
Posted By dave / Posted At
3/30/09 4:42 PM
OpenBD has a friendly URL servlet as well.
Also, once you're proxying you shouldn't need to specify a document root for your virtual hosts ... unless I'm missing something about your configuration. Apache doesn't need to know where the documents are since it's just proxying out to Tomcat anyway.
Posted By Matt Woodward / Posted At
3/31/09 6:09 PM
@Matt, with the RewriteRule I'm only proxying .cfm / .cfc requests and letting Apache serve everything else (so, yes, I do need DocumentRoot).
Posted By Sean Corfield / Posted At
3/31/09 6:33 PM
Yep, just noticed that after I made the comment.
Posted By Matt Woodward / Posted At
3/31/09 7:29 PM
Hi all. It looks like Craig Kaminsky has posted a solution for this. Using the 'urlrewritefilter' jar file available from Google Code, you can get SES support for Railo under Tomcat.
Craig's post is at:
http://craigkaminsky.blogspot.com/2009/04/mango-blog-on-aptana-cloud-with-railo.html
Posted By Damon Gentry / Posted At
4/16/09 8:24 AM
Hi Sean, I've been playing around with Tomcat and deployed Railo on it as the ROOT app (as you described in your posts) running a ColdBox app. as you know, ColdBox SES urls take on the form of "index.cfm/handler/action." I found that I could get these form of URLs to work in Tomcat by just adding the following servlet mapping in the app's web.xml file:
<servlet-mapping> <servlet-name>CFMLServlet</servlet-name> <url-pattern>/index.cfm/*</url-pattern> </servlet-mapping>
By doing this, I can still use the cgi.PATH_INFO variable, as well.
Posted By Tony Garcia / Posted At
4/18/09 10:07 AM
@Tony, thanx for that. I'll have to try it out when I rebuild my Tomcat env for multiple webs in the next few days. I keep reading SES URLs just don't work on Tomcat so I hadn't actually tried it...
Posted By Sean Corfield / Posted At
4/18/09 2:26 PM
If I'm write, where you proxy ajp://localhost:8009 I could use ajp://projectA.localhost:8009 in one Apache virtual host, and ajp://projectB.localhost:8009 in another, right ?
Posted By Tom Chiverton / Posted At
4/21/09 7:03 AM
@Tom, yup, you can proxy to any servers and you can use different ones in each vhost.
Posted By Sean Corfield / Posted At
4/21/09 10:08 AM
You need to proxy a few other paths to make things like Flex Remoting working. The complete set is:
ProxyPreserveHost On ProxyPassReverse / ajp://localhost:8009/
RewriteEngine On RewriteRule ^/(.*\.cf[cm])$ ajp://localhost:8009/$1 [P,L]
RewriteRule ^/flashservices/gateway(.*)$ ajp://localhost:8009/flashservices/gateway$1 [P,L] RewriteRule ^/messagebroker/(.*)$ ajp://localhost:8009/messagebroker/$1 [P,L] RewriteRule ^/flex2gateway/(.*)$ ajp://localhost:8009/flex2gateway/$1 [P,L] RewriteRule ^/openamf/gateway/(.*)$ ajp://localhost:8009/openamf/gateway/$1 [P,L]
Posted By Tom Chiverton / Posted At
6/4/09 2:05 PM
Post Your Comments
Hosting provided by