2

I have a server running an established PHP site, as well as some Django apps.

Currently, a VirtualHost set up for PHP listens on port 80, and requests to certain directories are proxied to a VirtualHost set up for Django with WSGI.

I'd like to change it so Django handles anything not existing as a PHP script or static file.

For example,

/ ->parsed by PHP as index.php
/page.php ->parsed as PHP normally
/images/border.jpg ->served as a static file
/johnfreep ->handled by Django (interpreted by urls.py)
/pages/john ->handled by Django
/(anything else) - > handled by Django

I have a few ideas. It seems the options are 'php first' or 'wsgi first'.

  • set up Django on port 80, and set Apache to skip all the known PHP, CSS or image files. Maybe using SetHandler? Anything else goes to Django to be parsed by urls.py.

  • Set up a script referring everything to Django as a 404 handler on PHP. So, if a file is not found for a name, it sends the request path to a VirtualHost running Django to be parsed.

Mark Snidovich
  • 133
  • 1
  • 5

1 Answers1

4

Use method described in:

http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#The_Apache_Alias_Directive

Thus have DocumentRoot setup as normal for static files and php files etc. Then add:

AddHandler wsgi-script .wsgi

to Directory block for DocumentRoot, or globally for server.

You will though need to have:

Options ExecCGI

enabled for DocumentRoot now if you don't already.

Then also add:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /site.wsgi/$1 [QSA,PT,L]

where site.wsgi is in DocumentRoot and is the WSGI script file which maps to your Django application.

In Django WSGI script file change it to use:

import django.core.handlers.wsgi

_application = django.core.handlers.wsgi.WSGIHandler()

import posixpath

def application(environ, start_response):
    # Wrapper to set SCRIPT_NAME to actual mount point.
    environ['SCRIPT_NAME'] = posixpath.dirname(environ['SCRIPT_NAME'])
    if environ['SCRIPT_NAME'] == '/':
        environ['SCRIPT_NAME'] = ''
    return _application(environ, start_response)

That should be it.

Any request that maps to an actual file based resource under DocumentRoot, be it static file or php file, including as setup by DirectoryIndex, eg., index.php, will be handled normally. Any other URL which would otherwise result in 404, will instead be routed into the Django application.

The /johnfreep and /pages/john would have to have corresponding URL as if mounted at root, in the urls.py file.

If Django doesn't know what to do with a URL, then Django will return 404.

Read the wiki document for more information.

Graham Dumpleton
  • 5,990
  • 2
  • 20
  • 19
  • Thanks for the complete answer! That's just what I needed. – Mark Snidovich Jan 25 '11 at 03:39
  • I'll add a note for anyone else trying this: it was giving 403 Forbidden for every single URL (and thus driving me nuts as the rewrite seemed to be correct) until I added `Options +FollowSymLinks`. – Mark Snidovich Jan 25 '11 at 07:32
  • Yeah, forgot about that. RewriteRule is forbidden unless one of FollowSymLinks or SymLinksIfOwnerMatch options is set. Don't really understand the reasoning for that requirement. – Graham Dumpleton Jan 25 '11 at 08:11
  • Oddly, I have other rewrite rules that seemed to be working. This one triggered an error message saying that about FollowSymLinks though, which I saw when I finally had the bright idea to check the error logs. – Mark Snidovich Jan 25 '11 at 10:02