Remove duplicate extension on file with .htaccess - .htaccess

I've been playing around with .htaccess to try and rewrite images for a specific browser (Safari).
I have images uploaded that are named like: myimage.png.webp and would like to have the .webp removed leaving the myimage.png so that the <img> tags point to a duplicate file that isn't a WebP.
This is what I tried patching together so far, but it just resulted in a 500 Error and I'm getting myself confused with the rules now. Can anyone help?
#RewriteCond %{HTTP_USER_AGENT} Safari
# check if an image was requested
#RewriteCond %{REQUEST_FILENAME} .(jpe?g|gif|bmp|png|svg).webp -f
#RewriteRule ^.*/uploads/(.*).(svg|png|jpe?g|gif|bmp).webp$ https://%{HTTP_HOST}/uploads/$1.$2 [L,R=302]

Your directives appear to do the opposite of what you're trying to do, as if you were linking to the myimage.png.webp file and externally redirecting to the myimage.png file?
I assume you are already linking to the myimage.png file (as stated). We then need to do some feature sniffing to make sure that the browser can support webp files (and that the .webp file actually exists) before rewriting the request.
For example:
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.$2.webp -f
RewriteRule (.+)\.(png|jpe?g|gif)$ /$1.$2.webp [T=image/webp,L]
The T flag ensures we send back the appropriate mime-type for the webp response.
UPDATE: It seems you are actually linking to the .webp image and wish to rewrite the corresponding png/jpg/gif when webp is not supported (ie. Safari)...
# Rewrite images to WebP if they exist
RewriteCond %{HTTP_USER_AGENT} Safari
RewriteCond %{DOCUMENT_ROOT}/$1.$2.webp -f
RewriteRule (.*).(png|jpe?g|gif).webp$ $1.$2 [T=image/$2,L]
This isn't strictly correct:
Safari isn't the only browser that doesn't support webp images. Notably, there is IE11 (which still has a reasonable market share, certainly comparible to Safari in some demographics) and other minor browsers (eg. KaiOS). By checking the user-agent, you need to also update the rule when these browsers do support webp images. It is therefore preferable to instead test whether the browser actually supports image/webp images (or not) by checking the Accept HTTP request header.
The 2nd condition is checking whether the .webp image exists, before rewriting to the non-webp image. Presumably you want to check that the non-webp image exists (or remove this condition altogether - since the request will presumably "fail" anyway if the user-agent does not support webp images).
The returned mime-type will be incorrect if your images are .jpg (as opposed to .jpeg) since image/jpeg is the correct mime-type, not image/jpg. This is harder to fix, unless you split this into its own rule.
Try the following instead:
# Rewrite images to non-WebP if webp are not supported and they exist
RewriteCond %{HTTP_ACCEPT} !image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.$2 -f
RewriteCond $2#jpeg ^jpe?g#(.+)|(.+)#
RewriteRule (.+)\.(png|jpe?g|gif)\.webp$ $1.$2 [T=image/%1%2,L]
The (rather cryptic) 3rd condition extracts the required mime-type "part": png, jpeg or gif respectively, regardless of whether .jpg or .jpeg is requested. These are saved in the %1 and %2 backreferences. Note that these are mutually exclusive. Either %1 holds jpeg (and %2 is empty), OR %2 holds png or gif (and %1 is empty). So together they form the correct response.
Note that literal dots in the RewriteCond TestString don't need to be escaped, since this is an "ordinary" string. However, the literal dots in the RewriteRule pattern do need to be backslash escaped since this is a regex.

You may try this rule in your site root .htaccess:
RewriteCond %{HTTP_USER_AGENT} Safari
RewriteCond %{REQUEST_FILENAME}.webp -f
RewriteRule ^.+\.(?:svg|png|jpe?g|gif|bmp)$ $0.webp [L,NC]

I managed to get it working the way I need, and with a bit of help from the other two answers, my htaccess rule is doing what I expect:
# Rewrite images to WebP if they exist
RewriteCond %{HTTP_USER_AGENT} Safari
RewriteCond %{DOCUMENT_ROOT}/$1.$2.webp -f
RewriteRule (.*).(png|jpe?g|gif).webp$ $1.$2 [T=image/$2,L]
So this will take an image URL like this:
https://example.com/uploads/test.png.webp and swap it to a fallback duplicate image on Safari/iOS (where webp still isn't supported), and output to the browser: https://example.com/uploads/test.png

Related

htaccess: serve webp image instead of jpg or png if webp exist results in 404

I generated *.webp files that are named exactly like their png or jpg source. Then I added this to my .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# Does browser explicitly support webp?
RewriteCond %{HTTP_USER_AGENT} Chrome [OR]
# OR Is request from Page Speed
RewriteCond %{HTTP_USER_AGENT} "Google Page Speed Insights" [OR]
# OR does this browser explicitly support webp
RewriteCond %{HTTP_ACCEPT} image/webp [OR]
# AND does a webp image exists?
RewriteCond %{DOCUMENT_ROOT}/$1\.webp -f
# THEN send the webp image and set the env var webp
RewriteRule (.+\.(?:jpe?g|png))$ $1.webp [NC,L]
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
What I expect:
all jpg files load normal e.g /test/marc.jpg If a webp with the same name exists, serve a webp file via url /test/marc.jpg
This works of the webp file exists. But if I delete a webp file I get a 404 on the jpg or png url. Even old jpg or png urls then give a 404. Example:
/www/media/
.htaccess
marc.jpg
marc.webp
http://domain/marc.jpg serves the webp. I test this from chrome with cache disabled. When I delete the marc.webp I get a 404 on http://domain/marc.jpg Why? RewriteCond %{DOCUMENT_ROOT}/$1.webp -f should fix this, right?
These two lines are not looking for the files you describe:
# AND does a webp image exists?
RewriteCond %{DOCUMENT_ROOT}/$1\.webp -f
# THEN send the webp image and set the env var webp
RewriteRule (.+\.(?:jpe?g|png))$ $1.webp [NC,L]
In both of these, $1 refers to the first captured match in the RewriteRule, which in this case is (.+\.(?:jpe?g|png)). If you request, "marc.jpg", that whole string matches, and will be placed in $1. The two lines therefore evaluate as:
If the file "marc.jpg.webp" exists, respond with "marc.jpg.webp"
Since it doesn't, the rule will not be run.
The condition you wanted was:
If the file "marc.webp" exists, respond with "marc.webp"
So you want $1 to contain only the "marc" part of the requested file; that's just a matter of moving the closing parenthesis:
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,L]
This doesn't explain why your rule appeared to work, and stopped working when you deleted a file. I suspect you have another rule somewhere else which is confusing the situation.

.htaccess - Open files without extension using .htaccess in subdomain

I downloaded a website, all files are coded in HTML and files do not have any extension.
My root domain is WordPress based.
I want to open all files as HTML using .htaccess - the files are in a subdomain.
I have tried this, think its for root domain only... I need help for subdomain.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /$1.php [L,QSA]
Your question is a bit vague as you've not given any examples of the URLs and file structure involved. However, if the HTML files do not have file extensions then it's quite probable that the Content-Type HTTP response header being sent from the server is either wrong or entirely absent (and reliant on the browser "content sniffing" - which is going to get mixed results).
We need to make some assumptions:
All the HTML files (that do not have file extensions) do not contain a dot anywhere in the file path.
The CSS and JS files do have appropriate file extensions ie. .css and .js, and are already returning the correct mime-type (Content-Type header).
If these too don't have file extensions, then they would need to be contained in specific directories so we can set the appropriate mime-type accordingly. We would also need to create exceptions with our rules in order to avoid conflicts.
So, in order to get the browser to interpret these files as HTML we need to make sure that we are sending the correct mime-type (ie. text/html) in the Content-Type response header. (I assume this is not the case currently.)
For example, using mod_rewrite in the .htaccess file in your subdomain (which I assume is separate from your main domain):
RewriteEngine On
RewriteRule ^([^.]+)?$ - [T=text/html]
However, as noted above, if your static resources (JS, CSS, images, etc.) are also devoid of file extensions then we'll need to add conditions to the above rule and create additional rules for the different file/mime types.
Aside:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /$1.php [L,QSA]
These directives that you posted in the question don't appear to have anything to do with your question, which has only added to the confusion in comments.

How to make webpage act like a subdirectory with htaccess

I'm building a website which has a profile page for each user.
I'd like the profile pages to be accessed through visiting a web address, eg:
example.com/profile/username
Obviously it would be impractical to create a new PHP file for each registered user, and so what I'm trying to do is redirect traffic from example.com/profile/(whatever) to example.com/profile, where I can then interrogate the URL and load the correct profile from a database.
However, I'm really struggling to work out how to do this with .htaccess. I've tried all sorts of redirects, etc, but can't seem to get it to work. Can anyone point me in the right direction?
The only other thing I've got in my .htaccess file at the moment is the below to remove .php from URLs:
# Remove .php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
Any advice gratefully appreciated!
redirect traffic from example.com/profile/(whatever) to example.com/profile
Note that you should internally rewrite directly to the file that handles the request, which I assume is /profile.php, rather than relying on another rewrite to later append the extension. I assume that code in /profile.php already processes the request as necessary.
I will also assume that "username" can consist only of the characters a-z, A-Z, 0-9, _ (underscore) and - (hyphen). Generally, you want to be as specific as possible.
Try something like the following:
RewriteEngine On
# Disable MultiViews to avoid conflicts with mod_negotiation
# (Since you are using "extensionless URLs")
Options -MultiViews
# Handle requests for `/profile/<username>
RewriteRule ^profile/([\w-]+)$ profile.php [L]
# Append the ".php" extension to any request that does not end in a file extension
RewriteRule ^([^.]+)$ $1.php [L]
Whilst the comment in your code states "Remove .php". The code actually appends the file extension to URLs that don't have one.
This currently only works for files in the document root (as per your original code), eg. /foo. It won't do anything with /foo/bar for instance.
The condition that checks against the file system (ie. RewriteCond %{REQUEST_FILENAME} !-f) was not required in your existing code, unless you have actual files that don't contain a file extension? I'm also assuming you do not need to access filesystem directories directly (as per your original code).
There is no need to escape literal dots when used inside a character class.

Htaccess not redirecting jpg/png images to script for webp conversion on the go

Code in htacces works on everything but images(the only thing that it needs to redirect). Using Cloudways and Prestashop . It work on local with Mamp
I have tried making it redirect averything(removing conditions) and it makes everything redirect( making it a php error as its not an image) but images are still not being redirected.
# Redirect images to webp-on-demand.php (if browser supports webp)
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)\.(jpe?g|png)$ webp-on-demand.php?source=%{SCRIPT_FILENAME} [NC,L]
I tried
# Redirect images to webp-on-demand.php (if browser supports webp)
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME}
RewriteRule webp-on-demand.php?source=%{SCRIPT_FILENAME} [NC,L]
which results in error on everything but images ( they return itself instead of compression result)
http://dev-cz.mamalabels.com/webp-on-demand.php?source=img/att/183/222-cs.png
url with script
https://dev-cz.mamalabels.com/img/att/183/222-cs.png
url of image
Image should return a page where script says how it got compressed (later returns a webp image) but it just keeps returning itself

mod_rewrite change extensions .gif/.jpg to .png

The rule I have been fruitlessly working with doesn't work, I am trying to get all images in 1 directory to load as .png The images in the directory are a mixture of .png, .jpg and .gif
I want to be able to load the file tree.jpg by going to tree.png (no files have the same name). I am sure my mistake is obvious or my entire attempt is wrong, I just can't work it out.
The htaccess file is in the same folder with the images, which is called /thumbs
RewriteEngine On
RewriteRule ^([^.]*)\.gif$ /thumbs/$1.png [R,L,NC]
I tried this also, but it just givens a broken link to both .gif and .png versions
RewriteEngine on
RewriteRule ^(.+)\.gif$ $1.png
I tried this too, but it adds in my server path to the URL for some reason
RewriteEngine on
RewriteRule ^([^.]*)\.gif$ $1.png [R,L,NC]
You can use this rule:
RewriteEngine on
RewriteRule ^([^.]+)\.png$ /$1.gif [L,NC,R]

Resources