We want to achieve this routing scheme [2]:
- /anything => static file, if it exists!
- / => the wsgi app
For some reason this isn't as straightforward as in Nginx. Example [1].
With Apache you have to employ mod_rewrite, which is not straightforward if you're not writing rewrite rules and conditions all day long :)
The first this is to alias the wsgi app to a different location than the root:
WSGIScriptAlias /wsgi /path/to/the/app.wsgi
We need to make the location of the static files the DocumentRoot:
DocumentRoot /path/to/static/files
<Directory /path/to/static/files>
Order deny,allow
Allow from all
</Directory>
And now the mod_rewrite dance:
RewriteEngine on
Set some conditions: if the request path is not a filename:
RewriteCond /path/to/static/files%{REQUEST_FILENAME} !-f
And not a directory:
RewriteCond /path/to/static/files%{REQUEST_FILENAME} !-d
Optional, exempt any other special locations (I have an Alias /media):
RewriteCond %{REQUEST_URI} !^/media
And finally the rewrite rule:
RewriteRule ^(.*)$ /wsgi$1 [PT,L]
- PT - Take the request to go through the URL mapping machinery (so Alias, WSGIScriptAlias etc are applied again for the resulting URL)
- L - Stops processing any other RewriteRule for this request. This is implied by PT but it put it there in case I forget this :).
The full configuration:
WSGIScriptAlias /wsgi /path/to/the/app.wsgi
DocumentRoot /path/to/static/files
<Directory /path/to/static/files>
Order deny,allow
Allow from all
</Directory>
Alias /media /path/to/media/files
<Directory /path/to/media/files>
Order deny,allow
Allow from all
</Directory>
RewriteEngine on
RewriteCond /path/to/static/files%{REQUEST_FILENAME} !-f
RewriteCond /path/to/static/files%{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/media
RewriteRule ^(.*)$ /wsgi$1 [PT,L]
[1] | In Nginx you would simply do something like: location / {
root /path/to/static/files;
try_files $uri $uri/ @wsgiapp;
}
location @wsgiapp {
# ...
}
... which is very straightforward. |
[2] | The given rewrite example will probably only work with Django. Explanation:
If you use a different framework then you probably need to patch the SCRIPT_NAME as noted by Graham in the comments. |