views:

23

answers:

2

I'm using Apache, Python (fastcgi), mod_rewrite.

I want

http://foo/bar

to redirect internally to

http://main.py?q=foo/bar

Now my .htacess file contains

Options +ExecCGI
AddHandler cgi-script .py
DirectoryIndex main.py

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule (.*) main.py?q=$1

Normally works fine. Redirects to main.py with the query-string q=foo/bar But if I have a script named foo.py it instead directs to foo.py instead of main.py.

I tried removing the RewriteConds and have the RewriteRule alone as a catch-all.

Then it always redirects to main.py ok, but the query-string passed to my script is q=main.py where it should be q=foo/bar

Now there's various kludges I could try involving restructuring my code, file layout etc, but I'd like figure out what's going on before it causes more problems down the track.

So I want to either a) stop it thinking that foo means foo.py or b) make it skip the existing file checks completely and pass on the correct query-string.

+1  A: 

It sounds like a problem with content negotiation. Try adding...

Options -Multiviews

...at the top of your .htaccess file.

Cags
+1  A: 

Your first problem is caused by MultiViews, which is resolving the non-existent resource foo/bar to the existing file foo.py, then likely passing it PATH_INFO of /bar. You can disable it in your .htaccess file by modifying your Options:

Options -MultiViews +ExecCGI

Using your original ruleset with MultiViews disabled should solve your problem. For the sake of completeness though, the reason why the query string ends up being q=main.py is because of the how the request is processed when you remove the rewrite conditions:

  • mod_rewrite receives the request, and foo/bar matches .* and is rewritten to main.py?q=foo/bar
  • mod_rewrite performs an internal redirect and assigns itself as the handler
  • The redirect is re-processed by mod_rewrite, and main.py matches .* and is rewritten to main.py?q=main.py
  • mod_rewrite performs an internal redirect and assigns itself as the handler
  • The redirect is re-processed by mod_rewrite, and main.py matches .* and is rewritten to main.py?q=main.py
  • mod_rewrite realizes that you're going to enter an infinite loop redirecting the same request to itself, and stops the redirection process
Tim Stone
Thanks! Your detailed answer was much appreciated.
Zarneth