Home > Blockchain >  Unexpected results with verified htaccess rewrite rules on Apache
Unexpected results with verified htaccess rewrite rules on Apache

Time:09-08

I have the following htaccess rewrite rules in my httpd.conf in a virtualhost section (Apache). If the request is just <filename> without <extension>, Apache will evaluate from HTTP_ACCEPT in the request header which file to return. In the directory /images, there are only .avif, .webp and .jpeg files, one version for each filename.

<Directory "/var/www/<document root>/images">
    RewriteEngine On

    RewriteCond %{HTTP_ACCEPT} image/avif 
    AddType image/avif .avif
    RewriteRule ^([^\.] )$ $1.avif [L] 

    RewriteCond %{HTTP_ACCEPT} image/webp
    AddType image/webp .webp
    RewriteRule ^([^\.] )$ $1.webp [L]

    AddType image/jpeg .jpeg
    RewriteRule ^([^\.] )$ $1.jpeg
</directory>

Thus, if a file isn't caught by the first two RewriteCond, it will receive the suffix .jpeg.

Testing this with https://htaccess.madewithlove.com returns exactly the expected results. And in the wild it works fine.

Now I've put a file with a different <extension> in the directory /images, called dm_schrift.svg. I would expect the request to be rewritten as dm_schrift.jpeg. Instead, the server returns the correct file:

$ curl -s -o /dev/null -D - https://<my domain>/images/dm_schrift.svg
HTTP/2 200
date: Thu, 08 Sep 2022 09:12:19 GMT
server: Apache
x-content-type-options: nosniff
strict-transport-security: max-age=15552000; includeSubDomains
last-modified: Tue, 30 Aug 2022 18:30:12 GMT
etag: "356-5e779921d3500"
accept-ranges: bytes
content-length: 854
vary: Accept-Encoding,User-Agent
cache-control: max-age=31536000, public, immutable
content-type: image/svg xml

(Regarding 'immutable': I get the same result if opening a new browser window, disabling cache in DevTools, loading the file and verifing, that it actually gets downloaded. The response is not from cache).

How can it be that I receive the file and not 404 for dm_schrift.jpeg?

EDIT: the following was part of the question and has been addressed in an answer, but was based on wrong assumptions. To be waived:

Another question regarding these rewrite rules: with these, a file requested as 'something' will be served as 'something.avif' in Chrome. Devtools/Network shows the whole name incl. extension. But the name wasn't included in the response header. That the file actually is 'avif' can be derrived from the 'content-type', but how does the browser know the whole filename incl. extension?

CodePudding user response:

You would seem to have already answered your question in the opening paragraph...

If the request is just <filename> without <extension>, Apache will evaluate...

And this follows the regex in your rules. ie. ^([^\.] )$ (Aside: the backslash-escape on the literal dot is not required here.

You are requesting the actual file in your example, complete with file extension, eg. /images/dm_schrift.svg. The regex does not match so the rules do not apply, so the file is simply served directly.

How can it be that I receive the file and not 404 for dm_schrift.jpeg?

This would only happen if you made the initial request without the file extension (as you stated initially).

Devtools/Network shows the whole name incl. extension. But the name wasn't included in the response header. That the file actually is 'avif' can be derrived from the 'content-type', but how does the browser know the whole filename incl. extension?

From the rules you've posted, the browser does not know the complete filename (including file extension) of the file on the server that is being rewritten to. The browser only knows the mime-type (ie. from the Content-Type header) - which doesn't really have anything to do with the file extension.

I have the following htaccess rewrite rules in my httpd.conf in a virtualhost section (Apache).

Just to clarify, the rules you've posted are inside a <Directory> section (which is inside a virtualhost section). This is very different to when the rules are directly inside the virtualhost section itself, which would inferred from your description.

<Directory> sections behave just like .htaccess, but note that any .htaccess files will override the corresponding <Directory> section in the server config.

  • Related