.htaccess - Check .jpg size and replace if match - image

I need to control all remotes .jpg matching sizes: 4456 and 4824. If match these bytes I need to replace with a default image. The below code is to replace a .jpg if doesn't exist.
RewriteCond %{REQUEST_URI} \.(jpeg|JPEG|jpg|JPG)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ /default-image.jpg [L]
I need that if a example.com/*.jpg have size (4456 | 4824) then replace with the default-image.jpg.
In PHP this is working like a charm for my needs but I would prefer to set in .htaccess.
$link = 'https://example.com/test.jpg';
$check_image = get_headers($link, 1);
$bytes = $check_image["Content-Length"];
if ($bytes < 5000) { ...

You can do the following on Apache 2.4 using an Apache expression with mod_rewrite:
RewriteCond %{REQUEST_URI} !^/default-image\.jpg$
RewriteCond expr "filesize(%{REQUEST_FILENAME}) =~ /4456|4824/"
RewriteRule \.jpe?g$ /default-image.jpg [NC,L]
If the requested image does not exist then the filesize() function simply returns 0 (no error). So, to handle non-existent images as well, then you could just change the regex to include 0, ie. /0|4456|4824/.
Aside:
RewriteCond %{REQUEST_URI} \.(jpeg|JPEG|jpg|JPG)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ /default-image.jpg [L]
In the first condition, there is no need to check jpeg|JPEG since you are using the NC (case-insensitive) flag on the directive. However, it is more optimal to perform this check in the RewriteRule pattern instead, rather than creating an additional condition.
There's no need to check that the request does not map to a directory (3rd condition), unless you also have directory names that end in .jpg etc. (unlikely). Filesystem checks are relatively expensive, so it is best to avoid them if possible.

Related

Keep doubles slashes in mod_rewrite

I try to rewrite urls like:
http://www.example.com/contoller/method/var1/var2/var3
to
http://www.example.com/index.php?q=contoller/method/var1/var2/var3
My rewrite rules are as below:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
It works well except with doubles slashes. Indeed, there are replaced by singles slashes.
I would like to be able to use it when a var is empty. For example, if the var2 is empty the URL contains a double slashes on the var2 location
Just use
RewriteRule ^ index.php [L]
The URL you're corrupting in the query string is already available within index.php as $_SERVER['REQUEST_URI'].

Assistance with .htaccess

I need the .htaccess file to allow all file and directories if they exist, but php extensions are not needed for existing files and everything else goes to the index file.(MVC type processing) I've tried a few things, but haven't got it right yet.
Examples:
www.example.com/search/
file exists as search.php and should display the file
www.example.com/shopping/mylist/file doesn't exist so should go to index.php
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ $1.php [L]
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
mod_rewrite is highly order dependent so let's think through it logically from most specific to least specific.
You will need a condition to check for the existence of the .php file based on a match from the () group in RewriteCond first. That will be two conditions followed by a RewriteRule to actually direct it into the .php file. Your example /search/ has a trailing slash, and that's why we'll first need to capture it as %1 with two RewriteCond. Otherwise, I would probably use %{REQUEST_FILENAME}.php -f to test if it exists. This sort of explains how the %1 backreference can be used in RewriteCond chain.
Then after applying that one to attempt to match a .php file, use the more generic index.php rule as you already have it, together with the two conditions to check whether the file actually exists.
RewriteEngine On
# Match an optional trailing slash on the filename
# and capture it as %1
RewriteCond %{REQUEST_FILENAME} ^(.+)/?
# And test if the match (without /) has a .php file
RewriteCond %1.php -f
# Rewrite everything up to an optional trailing /
# matched in the first RewriteCond
# into its .php suffix (add QSA to retain query string)
# It isn't necessary to give a full regex here since %1
# already contains everything needed
RewriteRule ^ %1.php [L,QSA]
# Now with that out of the way, apply the generic
# rule to rewrite any other non-existing file to index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# I used * instead of + so it also matches an empty url
RewriteRule ^(.*) index.php?url=$1 [QSA,L]
I have successfully tested this setup in a temporary directory. It appears to meet your requirements.

Friendly URL for images

Please suggest me what to put into .htaccess file.
I have PNG, GIF, JPG images on server http://domain.tld/images/anyimage.anyextension
Want to make URLs more friendly like a http://domain.tld/anyimage.anyextension
This I have now. First two strings change links as described. But last string doesn't change it back for server.
RewriteCond %{REQUEST_URI} ^/images/(.+)(\.gif|\.jpg|\.png)$ [NC]
RewriteRule ^image/(.+)$ /$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.+)$ /images/$1 [L]
If I add
RewriteCond %{REQUEST_URI} ^/([^/.]+\.(png|gif|jpg))$ [NC]
RewriteCond %{DOCUMENT_ROOT}/image/%1 -f
RewriteRule ^([^/.]+\.(png|gif|jpg))$ /image/$1 [L,NC]
Right after previous query string rule then images don't open. If before there's no problem. What it could be? Do you have an idea how to fix it? The last string RewriteRule ^/?(.+)$ /?$1 [L] cause this conflict
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /\?([^\ ]+) [NC]
RewriteRule ^$ /%1? [R=301,L]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?(.+)$ /?$1 [L]
Not sure how that makes it more friendly, aside from it being shorter. You can try adding this to the htaccess file in your document root:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/([^/.]+\.(png|gif|jpg))$ [NC]
RewriteCond %{DOCUMENT_ROOT}/images/%1 -f
RewriteRule ^([^/.]+\.(png|gif|jpg))$ /images/$1 [L,NC]
Then you can change all of your links from http://domain.tld/images/anyimage.anyextension to http://domain.tld/anyimage.anyextension
The first condition checks to make sure the request is for anyimage.anyextension, as long as the extension is a case-insensitive png, gif, or jpg.
The second condition checks to make sure the requested image actually exists in the /images/ directory.
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /images/(.+)(\.gif|\.jpg|\.png) [NC]
RewriteRule ^image/(.+)$ /$1 [R=301,L]
This redirects the browser to the non-/image/ URL. There's 2 completely different things going on here. One deals with the browser and the other deals with content on the server. See the top part of this answer that explains how they are different.
The rules that you have won't work. First:
RewriteRule ^/(.+)$ /images/$1 [L]
will never match. URI's used to match against the regex of a RewriteRule in htaccess files have the leading slash removed, so no URI is going to start with a /. You need to get rid of it.
Secondly, once you do, you'll get a 500 internal server error because your rules will cause an internal infinite loop. You need to match against %{THE_REQUEST} to ensure that a browser is actually requesting a URL with the /images/ path in it, not what has been internally rewritten.

Rewrite rules confused

I am struggling to achieve this simple thing...
I have some static pages which should be like
www.domain.com/profile etc..
The problem is how to write the rewrite rules in order to ..
There would be some fixed rewrites
like /home
I want every file that exists not to be rewritten
www.domain.com/test.php should go to
test.php
Lastly if it is not found i want it to be redirected to static.php?_.....
RewriteRule ^/home/?$ /index.php?__i18n_language=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([^/]+)/?$ /static.php?__i18n_language=$1
This works ok but if i type index.php or test.php or even the mach from other redirection it gets me in static.php...
Please help!
According to your description you can use these rules:
# stop rewriting process if request can be mapped onto existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteRule ^ - [L]
# rewrite known paths /home, /foo, /bar, etc.
RewriteRule ^/(home|foo|bar|…)$ /index.php [L]
# rewrite any other path
RewriteRule ^ /static.php [L]
I haven't used this in a long time, but it's something I found, that should help. It is part of an old script that generates .httaccess files for redirecting from /usr/share/doc only when the doc isn't found:
The rule is "Check, and if the target url exists, then leave":
RewriteEngine On
RewriteBase /doc/User_Documents
### If the directory already exists, then leave
### We're just redirecting request when the directory exists but has been renamed.
RewriteCond %{REQUEST_FILENAME} User_Documents/([^/]+-[0-9][^/]*)
RewriteCond $PWD/%1 -d
RewriteRule .* - [L]
It's the [L] that means leave if one of the conditions is matched. In the old script, there are hundreds of generated rules (after [L]) that are skipped, because one of the conditions matched. In your case you would skip the rest of the rules when the target %{REQUEST_FILENAME} is found.
So, I suggest, before the redirection rule:
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]

mod_rewrite: what does this RewriteRule do?

Given these conditions (I know what they mean/do):
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
What does the first rule do? What is that lonely dash for?
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ /index.php [NC,L]
I've been using this for quite some time now in combination with the Zend Framework, but I never really got what the first rule does exactly.
The RewriteCond directive just describes an additional condition for a RewriteRule directive. So RewriteCond must always be associated with a RewriteRule.
In your case the three RewriteCond probably belong to the first RewriteRule like this:
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
Now this rule is applied if the pattern of the RewriteRule matches the current request URL (per-directory path stripped before) and if the condition is fulfilled.
In this case the condition is only true if when mapping the request URL to the filesystem it matches either an existing file with the file size greater than 0 (-s), or a symbolic link (-l) or a directory (-d). So your rule will be applied for any URL (^.*$ matches anything) that can be mapped to something existing in your filesystem. The substitution - just means to not change anything. And the NC (no case, case insensitive, useless in this context) and L (last rule if applied) are flags that modify either the pattern, replacement or the execution of the rule.

Resources