oc-responsive-images-plugin
oc-responsive-images-plugin copied to clipboard
Webp .htaccess not working
First thanks for the amazing work!
I could not get the webp .htaccess rules working. I had to add the following lines to some existing OctoberCMS rules:
RewriteCond %{REQUEST_URI} !webp.php$
Without this apache2 would parse all the rules multiple times. I even had situations I reached the max 10 internal redirects.
I also had alot of issues with the DOCUMENT_ROOT rewrites (slash issues, I think dependend on how the document_root is set invhost). Eventually I picked the rules from the Wordpress webp express plugin:
# Redirect to existing converted image in same dir (if browser supports webp)
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME}.webp -f
RewriteRule ^/?(.*)\.(jpe?g|png)$ $1.$2.webp [NC,T=image/webp,E=EXISTING:1,E=ADDVARY:1,L]
# Redirect images to webp-on-demand.php (if browser supports webp)
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(/?(.+)\.(jpe?g|png))$ /plugins/offline/responsiveimages/webp.php?path=$1 [NC,L,E=REQFN:%{REQUEST_FILENAME},E=WPCONTENT:app]
With these changes everything worked perfectly! :)
Hope you understand the issues I have had and find it useful to improve things.
My full .htaccess:
## START OFFLINE.ResponsiveImages - webp-rewrite
# DO NOT REMOVE THESE LINES
<IfModule mod_setenvif.c>
# Vary: Accept for all the requests to jpeg and png
SetEnvIf Request_URI "\.(jpe?g|png)$" REQUEST_image
</IfModule>
<ifModule mod_rewrite.c>
RewriteEngine On
# Redirect to existing converted image in same dir (if browser supports webp)
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME}.webp -f
RewriteRule ^/?(.*)\.(jpe?g|png)$ $1.$2.webp [NC,T=image/webp,E=EXISTING:1,E=ADDVARY:1,L]
# Redirect images to webp-on-demand.php (if browser supports webp)
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(/?(.+)\.(jpe?g|png))$ /plugins/offline/responsiveimages/webp.php?path=$1 [NC,L,E=REQFN:%{REQUEST_FILENAME},E=WPCONTENT:app]
</ifModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REQUEST_image
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
## END OFFLINE.ResponsiveImages - webp-rewrite
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
##
## You may need to uncomment the following line for some hosting environments,
## if you have installed to a subdirectory, enter the name here also.
##
# RewriteBase /
##
## Uncomment following lines to force HTTPS.
##
# RewriteCond %{HTTPS} off
# RewriteRule (.*) https://%{SERVER_NAME}/$1 [R,L]
##
## Black listed folders
##
RewriteCond %{REQUEST_URI} !webp.php$
RewriteRule ^bootstrap/.* index.php [L,NC]
RewriteRule ^config/.* index.php [L,NC]
RewriteRule ^vendor/.* index.php [L,NC]
RewriteRule ^storage/cms/.* index.php [L,NC]
RewriteRule ^storage/logs/.* index.php [L,NC]
RewriteRule ^storage/framework/.* index.php [L,NC]
RewriteRule ^storage/temp/protected/.* index.php [L,NC]
RewriteRule ^storage/app/uploads/protected/.* index.php [L,NC]
##
## White listed folders
##
RewriteCond %{REQUEST_URI} !webp.php$
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} !/.well-known/*
RewriteCond %{REQUEST_FILENAME} !/storage/app/uploads/.*
RewriteCond %{REQUEST_FILENAME} !/storage/app/media/.*
RewriteCond %{REQUEST_FILENAME} !/storage/temp/public/.*
RewriteCond %{REQUEST_FILENAME} !/themes/.*/(assets|resources|dist)/.*
RewriteCond %{REQUEST_FILENAME} !/plugins/.*/(assets|resources)/.*
RewriteCond %{REQUEST_FILENAME} !/modules/.*/(assets|resources)/.*
RewriteRule !^index.php index.php [L,NC]
##
## Block all PHP files, except index
##
RewriteCond %{REQUEST_URI} !webp.php$
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteRule !^index.php index.php [L,NC]
##
## Standard routes
##
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Thank you very much for your feedback!
RewriteCond %{REQUEST_URI} !webp.php$
That's strange, this rule should not be required since the .htaccess should never reach October's PHP blacklist rules.
I have updated the rules a bit, would you mind testing if this works on your server (without the explicit whitelisting of the webp.php?) If I remove the %{DOCUMENT_ROOT}
in the webp.php RewriteRule, it no longer works on my server :thinking:
https://github.com/OFFLINE-GmbH/oc-responsive-images-plugin/blob/develop/views/webp-rewrite.htm#L6-L17
The latest updates work. But only worked with the RewriteCond %{REQUEST_URI} !webp.php$
lines. Thus I searched further. This behavior is documented by apace2 at: https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_l
So we need to use the END
flag instead of L
:+1:
It works using:
RewriteRule (.+)$ %{DOCUMENT_ROOT}/plugins/offline/responsiveimages/webp.php?path=$1 [NC,END]
Other point: It's important to only match the storage folder. For example. My theme images are now always served using webp.php
. Example theme file:
/themes/XXXX/assets/dist/app/apple-touch-icon.png
which is not a good thing to do. These files should just be served static.
Wow, thank you for this input! I did not know about the END
flag. Also, very good point concerning the storage folder. I came up with this new ruleset:
<ifModule mod_rewrite.c>
RewriteEngine On
# If the Browser supports WebP images, and the .webp file exists, use it.
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} ^/?storage/.*\.(jpe?g|png)
RewriteCond %{REQUEST_FILENAME}.webp -f
RewriteRule ^/?(.*)$ $1.webp [NC,T=image/webp,END]
# If the Browser supports WebP images, and the .webp file does not exist, generate it.
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} ^/?storage/.*\.(jpe?g|png)
RewriteCond %{REQUEST_FILENAME}\.webp !-f
RewriteRule ^/?(.*)$ %{DOCUMENT_ROOT}/plugins/offline/responsiveimages/webp.php?path=$1 [NC,END]
</ifModule>
Yep this is it :smiley: . Works great!
I also made a further little change to my project rules which makes sure only resized images are served as webp (RewriteCond %{REQUEST_URI} ^/?storage/.*/public/.*\.(jpe?g|png)
). But is a personal preference. I had big original images that were converted to webp, but timed out during the proces.
I think the main problem is, that the plugin creates a new file with the file extension itself. For example image.jpg becomes image.jpg.webp and the htaccess file recognize the following rule as true:
RewriteCond %{REQUEST_URI} ^/?storage/.*\.(jpe?g|png)
The plugin should create the new file without the jpg extension. I added a webp extension rule to exclude this case like so: see # !important!
## START OFFLINE.ResponsiveImages - webp-rewrite
# DO NOT REMOVE THESE LINES
<IfModule mod_setenvif.c>
# Vary: Accept for all the requests to jpeg and png
SetEnvIf Request_URI "\.(jpe?g|png)$" REQUEST_image
</IfModule>
<ifModule mod_rewrite.c>
RewriteEngine On
# If the Browser supports WebP images, and the .webp file exists, use it.
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} ^/?storage/.*\.(jpe?g|png)$
RewriteCond %{REQUEST_FILENAME}\.webp -f
RewriteRule ^(.*)$ $1.webp [L,T=image/webp,R=301]
# If the Browser supports WebP images, and the .webp file does not exist, generate it.
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} ^/?storage/.*\.(jpe?g|png)
RewriteCond %{REQUEST_URI} !\.(webp)$ # !important!
RewriteCond %{REQUEST_FILENAME}.webp !-f
RewriteRule ^/?(.*)$ plugins/offline/responsiveimages/webp.php?path=$1 [N,END]
</ifModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REQUEST_image
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
## END OFFLINE.ResponsiveImages - webp-rewrite
I'm drawing a blank. I currently fail to see the problem.
The frontend will issue a request for /stroage/any/file.jpg
, since this is in your markup. The htaccess rule sees that and checks for the same filename witht he webp extension. If it exists, it serves it. Otherwise it will redirect the request to the webp.php
.
Where do things go wrong?
Thats working great and is not the problem :) Requests like "...file.jpg.webm" are handled like a .jpg file not like a webm file. In my case I wanted the url to be the real webm path, so I did a 301 to the webm file if an image is requested and a webm does exists. If a webm doesnt exist, your case will trigger and create it.