Apache – Serve WebP Instead of PNG/JPG from PrestaShop /img Folder

.htaccessextensionimagesmod-rewriterewrite

First post here, so I hope I did it well.

I converted all png/jpg starting from my prestashop public_html folder to webp, and added rewrite rules to the .htaccess in order to have the webp served instead of png/jpg.

I based my rewrites on the already existing prestashop rewrites.
Where I had:
RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.jpg [L]
I ended up doing:

RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.webp [L]
RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.webp$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.webp [L]
RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.jpg [L]

Which works: I got jpg URL serving webp images, so far so good (I know still need to implement

#RewriteCond %{HTTP_ACCEPT} image/webp
#RewriteCond %{DOCUMENT_ROOT}/$1.webp -f

and as well try to figure out if I should leave [L] or do [L,T=image/webp] or do [T=image/webp,E=REQUEST_image], which is why I am reading apache related docs and crawling the web about rewrite related topics which is quiet huge indeed.

Ok, so back to the main topic, I saw that I was missing a webp rewrite for the images the prestashop stores in public_html/img folder.

Then I tried the following (and so other variants):

RewriteRule ^/img/(.+)\.jpe?g$ /img/$1.webp [L]
RewriteRule ^/img/(.+)\.png$ /img/$1.webp [L]

^— NOT OK… still serving jpg/png type images from the img directory (double checked the MIME Type).

Note that:

  1. Every time I changed .htaccess and tried a solution, I cleared the prestashop cache, just in case (despite knowing the .htaccess being read at every request).
  2. webp images corresponding to jpg/png in img folder exist.
  3. image file perms is correct in img folder and indeed in all stuff under public_html
  4. In img folder in prestashop, there is another .htaccess, which restricts the type of files that can be served from this folder, and I added already webp, just in case someone should ask.

UPDATE: As requested by MrWhite, adding the .htaccess of the img folder

<IfModule mod_php5.c>
    php_flag engine off
</IfModule>

# Apache 2.2
<IfModule !mod_authz_core.c>
    Order deny,allow
    Deny from all
    <Files ~ "(?i)^.*\.(webp|jpg|jpeg|gif|png|bmp|tiff|svg|pdf|mov|mpeg|mp4|avi|mpg|wma|flv|webm|ico)$">
        Allow from all
    </Files>
</IfModule>

# Apache 2.4
<IfModule mod_authz_core.c>
    Require all denied
    <Files ~ "(?i)^.*\.(webp|jpg|jpeg|gif|png|bmp|tiff|svg|pdf|mov|mpeg|mp4|avi|mpg|wma|flv|webm|ico)$">
        Require all granted
    </Files>
</IfModule>

Please could you guys kindly help me here?

Best Answer

RewriteRule ^/img/(.+)\.jpe?g$ /img/$1.webp [L]
RewriteRule ^/img/(.+)\.png$ /img/$1.webp [L]

In .htaccess files, the URL-path that the RewriteRule pattern matches against, does not start with a slash. So the above directives will never match the requested URL, so won't do anything. In your earlier rules you are matching against a digit as the first character, not a slash.

For example, it should be:

RewriteRule ^img/(.+)\.jpe?g$ /img/$1.webp [L]

However...

In img folder in prestashop, there is another .htaccess

Depending on the directives contained in /img/.htaccess file then these directives might be completely overriding the mod_rewrite directives in the parent .htaccess file. The mod_rewrite directives in the parent .htaccess might not even be getting processed.

UPDATE: Having now seen the /img/.htaccess file then it's OK - these directives will not over the directives in the parent .htaccess file with regards to rewriting the request to the .webp images.

Since these additional rules only apply to the /img subdirectory and you already have a .htaccess file in the /img subdirectory then you could write these rules in the /img/.htaccess file instead (slight adjustment required). For example:

# /img/.htaccess

RewriteEngine On

RewriteRule ^(.+)\.jpe?g$ $1.webp [L]

The RewriteRule pattern matches against the URL-path relative to the directory that contains the .htaccess file. So, in this case, it does not match against the /img subdirectory.


To complete the rule and incorporate the other conditions you've mentioned you can do the following. Now back in the root .htaccess file:

# /.htaccess

# Rewrite image request to ".webp" if supported and exists
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
RewriteRule ^(img/.+)\.(jpe?g|png)$ $1.webp [L,T=image/webp]

If the corresponding .webp image is guaranteed to exist then you don't necessarily need the filesystem check (the second condition).

(I'm not sure why you would need E=REQUEST_image?)

And if using the .htaccess file in the /img subdirectory:

# /img/.htaccess

# Rewrite image request to ".webp" if supported and exists
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/img/$1.webp -f
RewriteRule ^(.+)\.(jpe?g|png)$ $1.webp [L,T=image/webp]

Aside:

RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.webp [L]
RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.webp$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.webp [L]
RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.jpg [L]

The 3rd rule isn't doing anything and should be removed. And the first two rules can be easily combined using regex alternation on the file extension. eg. (jpg|webp).

Related Topic