2

This post outlines how to use RewriteCond to serve images,js,and css files correctly. However, here is my .htaccess file (placed in a directory under the server root which is always included in the site's http links) (note that my question may be related to this other post but is acutally more specific):

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?lang=$1&menu1=$2&menu2=$3 [QSA,NC,L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?lang=$1&menu1=$2 [QSA,NC,L]
RewriteRule ^([^/]+)/?$ index.php?lang=$1 [QSA,NC,L]

The result is that the PHP page index.php is always served fine (with its rewrites working). Now, I thought that the lines:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

mean that, if we are serving a file or directory other than a PHP file then don't process the RewriteRule's. Am I wrong? Why are those two lines not working?

I've tried prepending the following line:

RewriteCond %{REQUEST_URI} !\.(gif|jpg|png|ico|css|js)$ [QSA,NC,L]

but it's not working (when I try to retrieve the root document I get an HTTP 500 internal server error).

4
  • Isn't it just the relative resource references to stylesheets and images? Or did your log indicate the request paths got rewritten? Commented Sep 7, 2015 at 11:45
  • But you are serving up a php file... it's called index.php At least that what your .htaccess code shows. What's the problem? Commented Sep 7, 2015 at 11:46
  • Yes, I am serving a single file index.php which includes or references everything else: the PHP file references the /css/style.cs and js/jquery.js files, but these are being rewritten, and I don't understand what the first two RewriteCods are doing in my .htaccess file and whether I need them or not, since so far they don't seem to have made any difference. Thanks. Commented Sep 7, 2015 at 11:49
  • I think your question hadn't be closed on unix.stackexchange.com . Commented Sep 7, 2015 at 12:47

1 Answer 1

2

Your problem is that you are only including the rewrite conditions once. Rewrite conditions are only for the RewriteRule immediately following the conditions. So you need conditions for each RewriteRule. Note the difference below.

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?lang=$1&menu1=$2&menu2=$3 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?lang=$1&menu1=$2 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?lang=$1 [QSA,NC,L]

Now if you want to save some lines of code, alternatively you can write your .htaccess rules this way and accomplish the same thing by adding the rule at the top so that if the requested file is a real file or real directory do nothing otherwise proceed with the rewrites below.

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.* - [L]

RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?lang=$1&menu1=$2&menu3=$3 [QSA,NC,L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?lang=$1&menu1=$2 [QSA,NC,L]
RewriteRule ^([^/]+)/?$ index.php?lang=$1 [QSA,NC,L]

Also fyi, the reason you get an 500 error on this line

RewriteCond %{REQUEST_URI} !\.(gif|jpg|png|ico|css|js)$ [QSA,NC,L]

is because RewriteCond does not support QSA or L flag. That is for RewriteRule.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your answer. That fixed it. Out of curiosity, what does the [OR] flag, and the - (dash) in the RewriteRule in the second snippet you included do? Since the first snippet you posted actually solved my problem, I guess I don't need such code, but perhaps you can explain a little bit about what these do in the second snippet you posted.
@JohnSonderson please accept the answer since it solved your issue. Now the OR flag is just that. It means if the first condition matches OR the 2nd condition matches then do the following rewriterule. The dash says for the rule to do nothing. so it basically just stops right there. The 2nd snippet is less code and my preference but the first might be easier to understand if you're learning mod_rewrite.
Thanks. I now understand the dash. But the [OR], doesn't the [OR] hold anyways. After all, a generic file is either a file OR a directory (cannot be both). This is what's confusing me. Without the OR the two directives cannot certainly be ANDed. I will accept once I understand this issue.
@JohnSonderson accepting and an answer is not really done by having a complete understanding of how something works. I fixed the code you had an issue with. :) Not really getting how OR works is not really in the scope completely because that then becomes a training situation. Please have a look at the documentation scroll down to the bottom #6, It gives a good explanation and hopefully that it's clearer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.