iRector
iRector

Reputation: 1984

mod_rewrite: Image file name being mistaken as rewrite value

In my .htaccess file I have this rewrite rule:
RewriteRule example actual-page.php [L]

Which simply rewrites:
www.mysite.com/example to www.mysite.com/actual-page.php

The issue I'm having causes images with example in the file name (my_example.png), to not load due to the confusion with the rule.

I've fixed my problem by changing the rule to:
RewriteRule /example /actual-page.php [L]

I just want to know what the correct solution to this would be. I still have a lot to learn in the world of mod_rewrite, and I want to know if there's some implemented fix to this kind of issue, or if you really are just supposed to make the rule more specific.

Upvotes: 0

Views: 109

Answers (2)

Sven
Sven

Reputation: 70863

Your rewrite rule RewriteRule example actual-page.php [L] means:

Find the regular expression example in the current url and if found, replace the URL with actual-page.php. And then terminate the rewrite process and ignore further rules (L-flag).

This regular expression will trigger if the string "example" occurs anywhere in the url, including "example.png", but also "another-example-from-a-different-url".

So it is a very good idea to make sure you do not search anywhere with your regular expression, but to tell it to match the entire url string, or at least a significant part. The syntactic characters to do so are "^" for "string start" and "$" for "string end". This would change your rule to RewriteRule ^example$ actual-page.php [L].

On the other hand this might now not work, because the url really contains a slash, which is not allowed to match anymore. You might add it: RewriteRule ^/example$ actual-page.php [L]. Note that the query string is never used in this match, you cannot detect it in the RewriteRule, but would have to use a RewriteCond clause in front of it.

The generic use case for rewriting any virtual url into an existing PHP script, but not touch any existing resources like HTML files, images etc. would be like this:

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule .* - [L]
RewriteRule .* php-script.php [L]

This has an inverse logic: If the first rule matches, and the requested filename is either a file, or a directory or a symbolic link, then the rewriting does not take place. This will cancel rewriting if a real ressource is requested. Otherwise the same URL is tried in the second RewriteRule, and the php-script.php is executed and can then analyze the requested URL and act upon it.

Upvotes: 1

zerkms
zerkms

Reputation: 254926

Prepend your rule with this line:

RewriteCond %{REQUEST_FILENAME} !-f

It means that the following rule will only match if the requested url isn't a real file.

Upvotes: 2

Related Questions