Section 18.2. Using mod_rewrite or mod_proxy to Connect to CherryPy


18.2. Using mod_rewrite or mod_proxy to Connect to CherryPy

Because we don't have time to cover every possible configuration, we have to content ourselves to showing you how to set TurboGears up behind Apache. If for some reason you have to install behind another server, however, you can find good recipies at turbogears.org, and lots of helpful people on the mailing list.

We chose Apache because it is the most widely used web server in the world, it runs on Linux, Windows, and OSX; and if you are using shared hosting, it's almost certainly what's already installed.

When using mod_rewrite or mod_proxy to forward requests from the Apache front-end server to your TurboGears application, Apache uses the HTTP protocol to talk to CherryPy. Basically, whenever Apache gets a valid request that matches the criteria you set up, Apache forwards the HTTP request that it received from the browser to CherryPy, waits for a response from CherryPy, and then forwards that response right back down to the browser.

This is probably the easiest and most flexible way to run CherryPy behind a web server. The configuration details behind using mod_rewrite or mod_proxy are Apache specific, but this same technique is also likely to be your best choice when using other web servers such as IIS or lighttpd.

18.2.1. Advantages/Drawbacks of Using a Proxy in front of CherryPy

The advantages of this method are as follows:

  • Easy to set up.

  • You can still access your CherryPy directly (by using the port number), which is nice for debugging.

  • It's fast. (Rough tests have shown that the overhead associated with forwarding the request/response can be as little as 1ms per request.)

The drawbacks of this method are as follows:

  • You have to use special headers to get the actual Host header of the request and the IP address of the browser. This is because to CherryPy, requests will look like they come from the local Apache server rather than the remote browser. In the case of Apache, you get the original Host header in the X-Forwarded-Host header and the IP address of the browser in the X-Forwarded-Host header. Fortunately, there is an easy way to tell CherryPy to use these special headers (see 18.2.4).

  • You are responsible for starting/stopping your CherryPy server and making sure that it restarts automatically in case it crashes. Again, this can be achieved using various techniques (see 18.2.5).

18.2.2. Configuring Apache with mod_rewrite

Let's assume that your CherryPy process is listening on port 80. All you have to do is tell Apache to forward requests to CherryPy. If you use mod_rewrite, this is done like this:

RewriteEngine on RewriteRule ^(.*) http://127.0.0.1:8000$1 [P]


The equivalent with mod_proxy is this:

ProxyPass           /   http://localhost:2432/ ProxyPassReverse    /   http://localhost:2432/


For this to work, you have to make sure that the mod_rewrite or mod_proxy module is loaded (either dynamically, or statically linked when Apache was built). For more details about mod_rewrite or mod_proxy, refer to their documentation:

  • mod_rewrite (http://httpd.apache.org/docs/2.0/misc/rewriteguide.html)

  • mod_proxy (http://httpd.apache.org/docs/2.0/mod/mod_proxy.html)

18.2.3. Configuring Apache to Serve Static Content Directly

Chances are, your web server will be faster than CherryPy for serving static files. So, you should take advantage of this. Fortunately, it is trivial to achieve this with mod_rewrite:

RewriteEngine on RewriteRule ^/static(.*) /home/myuser/static$1 [L] RewriteRule ^(.*) http://127.0.0.1:8000$1 [P]


This way, if you have a static file /home/myuser/static/foo.html, it will be available at http://<domain>/static/foo.html.

18.2.4. Configuring CherryPy to Run Behind a Web Server

CherryPy doesn't really care whether it runs exposed or behind another web server. It works identically in both cases.

However, Apache modifies requests slightly before forwarding them to CherryPy:

  • The Host header gets changed to localhost.

  • The original host header gets put in X-Forwarded-Host.

  • The request comes from Apache rather than the remote browser, so the IP address of the request will be that of the Apache server (127.0.0.1 if you run Apache locally) instead of being the actual IP address of the remote browser.

  • The IP address of the remote browser gets put in X-Forwarded-For.

The remote IP address is not needed by CherryPy apart from logging purposes, but if you're logging the IP address inside your TurboGears application, make sure you use the X-Forwarded-For header from the request.

However, the Host header is needed when you need to generate "canonical" URLs (that is, URLs that include the full protocol and domain name). You might think that you can just use relative URLs everywhere in your app (such as: /my/url) and then you'll be fine. But this is only half true. Chances are you'll use some redirects (HTTP code 302 or 303) in your application, and the HTTP protocol specifies that you must include the canonical URL when you issue a redirect. And so, you really do need the full host path for your application.

Fortunately, we can use a CherryPy filter to make this easier. CherryPy's base_url_filter has an option to use the X-Forwarded-For value as the base URL, which gets used to generate full (canonical) URLs. All you have to do to get this automagical behavior is to add the following three lines to prod.cfg:

[/] base_url_filter.on = True base_url_filter.use_x_forwarded_host= True


Unfortunately the "X-…" headers are only there if you use Apache 2.0 or later. If you use Apache 1.3, the original Host and IP address are lost. In that case, you can still use base_url_filters, but you have to hard-wire the base URL into base_url_filter like this:

[/] base_url_filter.on = True base_url_filter.base_url = 'http://your.domain.com' base_url_filter. use_x_forwarded_host= False


Of course, you will want to replace your.domain.com with your actual domain! This will set the base_url to a static value, which isn't quite as nice, but, hey, at least it works.

18.2.5. Making Sure That CherryPy Stays Up

When you run CherryPy behind your web server, you're responsible for making sure that your CherryPy server starts up when the machine boots and restarts if it ever crashes. This can be achieved using various techniques:

  • Using a cronjob. (This is a crude way of doing it.) Set up a cronjob that checks every few minutes whether the process is still running. If it isn't, simply restart it. (If you're on Windows, you can set up a Scheduled Task to do the same thing.)

  • Using a tool such as Supervisor (or FireDaemon on Windows). These tools can monitor other processes and restart them if the process ever goes down.

  • Using Apache to start CherryPy. The trick is to use Apache's error-handling mechanism to start CherryPy. If Apache tries to forward the request to CherryPy but CherryPy isn't running, Apache will display an error message. This error message can be customized, and we can tell Apache to run a CGI script instead. We can then use the CGI script to start CherryPy.

There are advantages and disadvantages to the three techniques. Unfortunately, lots of shared hosting environments won't let you run cronjobs frequently, and they are very picky about what long running processes they'll allow. So, sometimes you're stuck with the CGI script hack. Lucky for us, it works well and is easy to set up. All you have to do is tell Apache to run a CGI script when an error occurs (along with the other mod_rewrite rules):

RewriteEngine on ErrorDocument 502 /cgi-bin/autostart.cgi RewriteRule ^/cgi-bin/(.*) /home/myuser/autostart.cgi [L] RewriteRule ^/static(.*) /home/myuser/static$1 [L] RewriteRule ^(.*) http://127.0.0.1:8000$1 [P]


The autostart.cgi file can be a simple Python script that starts CherryPy in the background:

#!/usr/local/bin/python print "Content-type: text/html\r\n" print """""<html><head><META HTTP-EQUIV="Refresh" CONTENT="1; URL=/"></ head><body>Restarting site ...<a href="/">click here<a></body></html>""" import os os.setpgid(os.getpid(), 0) os.system('/usr/local/bin/python2.4 cherrypy-site.py &')


Note

We set the group ID of the process to 0. If you don't do that, Apache will kill the CGI process and its children (that is, the CherryPy process) after a while.





Rapid Web Applications with TurboGears(c) Using Python to Create Ajax-Powered Sites
Rapid Web Applications with TurboGears: Using Python to Create Ajax-Powered Sites
ISBN: 0132433885
EAN: 2147483647
Year: 2006
Pages: 202

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net