views:

75

answers:

3

I've tried every single example I could find, they all produce an internal server error. I have these rules set up (this works, no error):

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule ^((/?[^/]+)+)/?$ ?q=$1 [L]

So if it's not an existing file or an existing directory with an index.php we redirect. For instance, http://domain.com/foo/bar becomes http://domain.com/?q=foo/bar

Thing is, I want the trailing slash stripped. So take off the /? at the end of the rule. How do I make it so that http://domain.com/foo/bar/ becomes http://domain.com/foo/bar with a visible redirect first (fixing the client's URL), and only then the real, silent redirection to ?q=?

Everywhere I look I see this:

RewriteRule (.*)/$ $1 [R,L]

But it gives me a 500 error if I insert it before my rule.

+1  A: 

It looks like the simpler rewrite rule you mention at the end of your question should work. The problem is, the 500 error isn't really helpful in figuring out why it's not working. One way I've found useful in helping debug mod_rewrite errors is to enable it's logging. Add the following to your httpd.conf:

  RewriteLog "/usr/local/var/apache/logs/rewrite.log" 
  RewriteLogLevel 3 

Then try again, and look in the log to see what's going on. Once you're done, you can disable the log be setting the rewriteloglevel 0. See the mod_rewrite docs for details.

zigdon
Problem is, I don't have access to any `httpd.conf` that I'm aware of.
Core Xii
A: 

Try this rule in front of your current rule:

RewriteRule (.*)/$ /$1 [R,L]
Gumbo
That 500's as well.
Core Xii
+2  A: 

If foo/bar exists as a real directory, then the server will be redirecting the client to foo/bar/ (with the trailing slash). It has to do that in order for relative URLs to work correctly on the client. If you put in a rule to rewrite that back to foo/bar with a redirect then there will be a loop. An easy way to test if that's happening is to specify a path that doesn't exist at all (I assume from your index.php detection that the directory tree actually exists). The nonexistent path won't trigger the built-in redirect.

If I setup a similar set of rules to yours (plus the suggested slash-removal rule) I can see the difference between a directory that exists and one that doesn't. The ones that don't work as expected, the ones that do cause Firefox to say This page isn't redirecting properly. IE8 says something similar. Perhaps the Apache setup you're using can detect it and turns it into the 500 error?

Ben Jackson
That seems plausible. But then, are you saying it cannot be done? Alright, perhaps I should carry out the stripping of the trailing slash in index.php itself after the redirect. Thanks.
Core Xii
It can be done if you are willing to move the directory tree somewhere else. Or at least the part of the tree which isn't already populated with index.php. Keep in mind with your external slash-removing redirect, relative links are going to have the very problem the server is trying to avoid: A link `SRC="pic.jpg"` in the page you return for `.../foo/bar` will be transformed *by the client* to `.../foo/pic.jpg` rather than `.../foo/bar/pic.jpg`. This is the whole point of the server's slash-adding redirect.
Ben Jackson
With the whole URL rewriting scheme the need arises to establish a base address anyway, so it's hardly an added concern. That's what [<base>](http://www.w3schools.com/tags/tag_base.asp) is for.
Core Xii