mod_proxy
, and mod_proxy_html
In our sample setup we will have an Apache web server facing the world, and the web2py instance (using CherryPy) running on localhost port 8000. We have an existing website on example.com that we'll want to leave as is while making web2py and it's appliances availalbe via sub paths.
External Apache server: 192.168.1.1
Internal web2py instance: 127.0.0.1
CherryPy Port: 8000
External domain: example.com
External path to all web2py apps: /web2py/
Internal path to web2py apss: /
Below is an example Virtual Host configuration for example.com on our webserver located at 192.168.1.1. The <VirtualHost> portion of the configuration is our standard Virtual Host entry, and the important portions for web2py will be contained in the <Location> portion of the configuration.
<VirtualHost 192.168.1.1:80>
ServerName exmaple.com
<Location /web2py/admin/>
SSLRequireSSL
</Location>
<Location /web2py/>
ProxyPass http://127.0.0.1:8000/
ProxyPassReverse /
SetOutputFilter proxy-html
ProxyHTMLURLMap ^/(.*)$ /web2py/$1 R
</Location>
</VirtualHost>
The first <Location> section contains the path of the administration portion of web2py, we want to ensure that this is only accessible via SSL and as such use the SSLRequireSSL option on the "/web2py/admin/" path.
The second <Location> command sets up the sub path of our domain that is going to be proxied, and sent on to CherryPy and web2py. In our example we want to access web2py from http://example.com/web2py/ and we take the path portion of the URL and use it in the Location configuration
<Location /web2py/>
Inside the location we need to set up our proxy. To forward requests on /web2py/ to CherryPy we need to enable the proxy and tell Apache where to proxy requests. In this case we want to forward all requests on /web2py/ to our internal server on 127.0.0.1 on port 8000 and to the root of the server. (Note: ProxyPass and ProxyPassReverse will take the path portion of the external server from the path portion of the <Location> configuration)
ProxyPass http://127.0.0.1:8000/
We'll also want mod_proxy to rewrite any redirects that the internal server may try to send to our clients so that the user is always given a valid url from the point of view of the external server. As such we use the ProxyPassReverse option to configure how those redirects should be modified.
ProxyPassReverse /
The above line specifies that if the internal server tries to redirect to any path on the root or below of the web2py server, then the root path "/" should be replaced with "/web2py/".
Now we've got Apache and modproxy rewriting our header based redirects properly, but we still have the problem of links within the web2py applications. These will all point to locations that do not exist on the Apache web server, and that are not being proxied and forwarded to the web2py server. To reconcile this problem we need to take advantage of modproxy_html which can actually process any links it finds within the body of the html being passed through the proxy.
To enable modproxyhtml in our configuration we must first set an output filter for the proxied data to be passed through. To do this we use the SetOutputFilter option as such:
SetOutputFilter proxy-html
Finally we need to tell modproxyhtml what to look for inside of the html content. In this case we are going to give modproxyhtml a regular expression and use the ProxyHTMLURLMap option as such:
ProxyHTMLURLMap ^/(.*)$ /web2py/$1 R
The first portion of the command is the URL that we should search for, in this case, any links to the root of the internal server, and any sub paths. Then the second portion asks for the placements of "/web2py/" before the value we found in our search. The R at the end of our command tells modproxyhtml that this is a regular expression based search.
The configuration of modproxy and modproxy_html goes beyond the scope of this article. However, there are a few basic things you can check for if you are having trouble.
If you are using ProxyPass inside of a <Location> section then you don't need to pass the path to ProxyPass. If you aren't using ProxyPass inside of a <Location> section then the command takes two paramaters as such:
ProxyPass /web2py/ http://127.0.0.1:8000/
The option ProxyRequests should usually be set to off.
ProxyRequests off
http://httpd.apache.org/docs/1.3/mod/mod_proxy.html
http://httpd.apache.org/docs/2.0/mod/mod_proxy.html