Gust van de Wal Gust van de Wal - 6 days ago 6
Apache Configuration Question

htaccess not behaving like expected

I'm creating an htaccess with which I want to achieve 3 things:


  • remove trailing slash

  • redirect all requests that aren't
    css
    ,
    ico
    ,
    jpg
    ,
    js
    ,
    php
    or
    png
    files to index.php

  • redirect all files to view.php if the query string doesn't begin with
    a



At the moment it looks like this

RewriteEngine On
RewriteBase /test/
RewriteRule ^(.*)/$ $1 [N] # remove trailing slash

RewriteCond %{REQUEST_URI} !\.(css|ico|jpg|js|php|png)$ # if it isn't one of the files
RewriteRule . "index.php" [L] # then redirect to index

RewriteCond %{QUERY_STRING} !^a($|&) # if query doesn't start with a
RewriteRule . "view.php" [L] # then redirect to view


This way, the following test cases should be true:

http://127.0.0.1/test/contact -> http://127.0.0.1/test/index.php
http://127.0.0.1/test/contact/ -> http://127.0.0.1/test/index.php
http://127.0.0.1/test/contact.png -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact.png?a -> http://127.0.0.1/test/contact.png?a


When I try these out on this site, it shows me exactly these results.
In practice, however, when I'm trying out URLs, It completely breaks:

http://127.0.0.1/test/contact -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact/ -> Error 500
http://127.0.0.1/test/contact.png -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact.png?a -> http://127.0.0.1/test/contact.png?a


It seems as if the script always looks at the query-related part first, although with that in mind, it still doesn't make much sense to me that
/contact/
breaks. When I remove the query-related part though, the rest does work.

Did I forget about something? Is there a rule concerning the order of operation that I'm not aware of? Did I make a typo?

All input is appreciated!

P.S. I know that I will have to add a query that starts with an
a
for all local images, stylesheets, scripts and AJAX-calls. I'm doing this so that when people view media in a separate tab, I can create a fancy page around it, allowing people to navigate through all the media that is publicly present on the server.

Answer

Issues with your code:

  1. First all non-css/js/image requests are routed to index.php and then anything without ?a is routed to view.php so eventually index.php won't be used at all. You need to use a negated condition in last rule for anything that doesn't have .php extension..
  2. mod_rewrite syntax doesn't allow inline comments.
  3. You need R flag in first rule to change URL in browser.

You can use this code in /test/.htaccess:

RewriteEngine On
RewriteBase /test/

# if not a directory then remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [L,NE,R=301]

RewriteCond %{REQUEST_URI} !\.(css|ico|jpe?g|js|php|png)$
RewriteRule . index.php [L]

RewriteCond %{QUERY_STRING} !(^|&)a [NC]
RewriteRule !\.php$ view.php [L,NC]
Comments