Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filename-based cache busting issue for Apache 2.2+ #47

Closed
warrenski opened this issue Nov 14, 2014 · 11 comments
Closed

Filename-based cache busting issue for Apache 2.2+ #47

warrenski opened this issue Nov 14, 2014 · 11 comments

Comments

@warrenski
Copy link

In the Apache RewriteRule that manages filename-based cache busting, the RewriteCond directive no longer work as intended for Apache versions 2.2+

Luckily the fix is quite simple; all you need to do is add the DOCUMENT_ROOT variable before the REQUEST_FILENAME variable.

Apache < 2.2:

RewriteCond %{REQUEST_FILENAME} !-f

Apache > 2.2:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f

On Apache 2.2.29 I've confirmed that the cache-busting RewriteRule works as intended after making this change (i.e. Apache serves the resource whose filename happens to match the regexp pattern).

@alrra
Copy link
Member

alrra commented Nov 14, 2014

@warrenski Thank you for taking the time to open this issue!

the RewriteCond directive no longer work as intended for Apache versions 2.2+

@warrenski Can you provide more details? What exactly do you mean by "RewriteCond directive no longer work as intended"? What OS are you using? If you can say, what other configs do you have? Can you provide some examples for which the configs do not work as intended?

Thanks!

Apache < 2.2:

This project only supports Apache v2.2.0+ (the use of older versions no longer being recommended).

Note: Looking at our test results, everything seems to work (see results for v2.2.x and v2.4.x).

@alrra
Copy link
Member

alrra commented Nov 16, 2014

Closing until more details are provided that would help reproduce the issue.

@alrra alrra closed this as completed Nov 16, 2014
@warrenski
Copy link
Author

@alrra I'm on CentOS 5.6 running Apache 2.2.29 compiled from source with a basic set of modules active, including mod_rewrite which is statically compiled and the only module of relevance for this particular section of config. I have added your filename-based cache busting config inside of a VirtualHost container inside of httpd.conf and restarted Apache after running a configtest.

It goes without saying that the RewriteRule does what is intended (i.e. it achieves dynamic versioning of resources to invalidate browser cache). As an example, if you have a physical file on disk named "foo.css" and you referenced it via a URL as "foo.12345.css", then the contents of the file is correctly returned by the server.

However, in my case, if you additionally happened to have a file on disk named "foo.12345.css", then rather than the server returning its contents (due to the presence of the RewriteCond directive blocking the RewriteRule directive), the contents of "foo.css" was incorrectly being returned. Logically this meant that the RewriteCond directive was not able to find REQUEST_FILENAME on disk. The solution for me was to prepend DOCUMENT_ROOT in front of REQUEST_FILENAME.

Apache's mod_rewrite documentation does discuss some things to be aware of when using REQUEST_FILENAME, but I haven't digested or tested beyond what I've written above. Reading the notes now quickly, it appears that because I'm inside of a VirtualHost, REQUEST_FILENAME is unavailable. As I say, it might just be my situation, but hopefully if anyone else has a similar issue they will find this workaround.

See also:
http://www.harecoded.com/apache-rewritecond-f-check-file-exists-solution-2246468

@alrra alrra reopened this Nov 17, 2014
@alrra
Copy link
Member

alrra commented Nov 17, 2014

@warrenski Thanks for providing the details.

As I say, it might just be my situation,

No, this seems like a legitimate case, and we should address it.

Can you open a pull request that updates the existing code with the solution you have so that if this gets merged you get the credit for it? Thanks!

@warrenski I'll dig a little bit more into this, hopefully tonight.

@warrenski
Copy link
Author

@alrra No worries on getting credit - we're using SVN over here so don't think I can facilitate the pull request. Good luck and thanks for looking into it.

@AD7six
Copy link
Member

AD7six commented Nov 18, 2014

Using 2.4.10 I was not able to reproduce a problem (I also performed the same test with 2.2.22).

This is with only the following physical files:

  • css/main.12345.css
  • css/main.css

and h5bp's .htaccess file with the filename-based cache busting rules uncommented.

A request that should NOT be rewritten

Requesting a file matching the pattern that does exist:

$ curl -i http://apache.h5bp.dev:81/css/main.12345.css
HTTP/1.1 200 OK
Date: Tue, 18 Nov 2014 09:20:04 GMT
Server: Apache/2.4.10 (Debian)
Last-Modified: Tue, 18 Nov 2014 08:56:46 GMT
Accept-Ranges: bytes
Content-Length: 24
Cache-Control: max-age=31536000
Expires: Wed, 18 Nov 2015 09:20:04 GMT
X-Content-Type-Options: nosniff
Content-Type: text/css; charset=utf-8

main.12345.css contents

The result is the contents of main.12345.css.

With log level set to alert rewrite:trace8 - the server logs showed:

[Tue Nov 18 09:19:57.547588 2014] [mpm_prefork:notice] [pid 9943] AH00163: Apache/2.4.10 (Debian) configured -- resuming normal operations
[Tue Nov 18 09:19:57.547642 2014] [core:notice] [pid 9943] AH00094: Command line: '/usr/sbin/apache2'
[Tue Nov 18 09:20:04.759455 2014] [rewrite:trace3] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.12345.css -> css/main.12345.css
[Tue Nov 18 09:20:04.759499 2014] [rewrite:trace3] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] applying pattern '^' to uri 'css/main.12345.css'
[Tue Nov 18 09:20:04.759515 2014] [rewrite:trace4] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] RewriteCond: input='off' pattern='!=on' => matched 
[Tue Nov 18 09:20:04.759526 2014] [rewrite:trace4] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] RewriteCond: input='apache.h5bp.dev:81' pattern='^www\\.(.+)$' [NC] => not-matched
[Tue Nov 18 09:20:04.759534 2014] [rewrite:trace3] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.12345.css -> css/main.12345.css
[Tue Nov 18 09:20:04.759542 2014] [rewrite:trace3] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] applying pattern '(^|/)\\.' to uri 'css/main.12345.css'
[Tue Nov 18 09:20:04.759552 2014] [rewrite:trace3] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.12345.css -> css/main.12345.css
[Tue Nov 18 09:20:04.759560 2014] [rewrite:trace3] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] applying pattern '^(.+)\\.(\\d+)\\.(css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$' to uri 'css/main.12345.css'
[Tue Nov 18 09:20:04.759578 2014] [rewrite:trace4] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] RewriteCond: input='/var/www/html5-boilerplate/css/main.12345.css' pattern='!-f' => not-matched
[Tue Nov 18 09:20:04.759587 2014] [rewrite:trace1] [pid 9946] mod_rewrite.c(475): [client 10.10.10.1:59792] 10.10.10.1 - - [apache.h5bp.dev/sid#7fe385de08e8][rid#7fe385d1e0a0/initial] [perdir /var/www/html5-boilerplate/] pass through /var/www/html5-boilerplate/css/main.12345.css

A request that should be rewritten

Compared to a request matching the pattern that does not exist:

$ curl -I http://apache.h5bp.dev:81/css/main.123456.css
HTTP/1.1 200 OK
Date: Tue, 18 Nov 2014 09:24:16 GMT
Server: Apache/2.4.10 (Debian)
Last-Modified: Tue, 29 Oct 2013 15:17:17 GMT
Accept-Ranges: bytes
Content-Length: 5605
Vary: Accept-Encoding
Cache-Control: max-age=31536000
Expires: Wed, 18 Nov 2015 09:24:16 GMT
X-Content-Type-Options: nosniff
Content-Type: text/css; charset=utf-8

The result is the contents of main.css.

With the following log entries:

[Tue Nov 18 09:24:16.238036 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.123456.css -> css/main.123456.css
[Tue Nov 18 09:24:16.238084 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] applying pattern '^' to uri 'css/main.123456.css'
[Tue Nov 18 09:24:16.238103 2014] [rewrite:trace4] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] RewriteCond: input='off' pattern='!=on' => matched 
[Tue Nov 18 09:24:16.238120 2014] [rewrite:trace4] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] RewriteCond: input='apache.h5bp.dev:81' pattern='^www\\.(.+)$' [NC] => not-matched
[Tue Nov 18 09:24:16.238131 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.123456.css -> css/main.123456.css
[Tue Nov 18 09:24:16.238141 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] applying pattern '(^|/)\\.' to uri 'css/main.123456.css'
[Tue Nov 18 09:24:16.238153 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.123456.css -> css/main.123456.css
[Tue Nov 18 09:24:16.238164 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] applying pattern '^(.+)\\.(\\d+)\\.(css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$' to uri 'css/main.123456.css'
[Tue Nov 18 09:24:16.238181 2014] [rewrite:trace4] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] RewriteCond: input='/var/www/html5-boilerplate/css/main.123456.css' pattern='!-f' => matched 
[Tue Nov 18 09:24:16.238196 2014] [rewrite:trace2] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] rewrite 'css/main.123456.css' -> 'css/main.css'
[Tue Nov 18 09:24:16.238207 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] add per-dir prefix: css/main.css -> /var/www/html5-boilerplate/css/main.css
[Tue Nov 18 09:24:16.238219 2014] [rewrite:trace2] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] strip document_root prefix: /var/www/html5-boilerplate/css/main.css -> /css/main.css
[Tue Nov 18 09:24:16.238232 2014] [rewrite:trace1] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa19123c0a0/initial] [perdir /var/www/html5-boilerplate/] internal redirect with /css/main.css [INTERNAL REDIRECT]
[Tue Nov 18 09:24:16.238334 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.css -> css/main.css
[Tue Nov 18 09:24:16.238349 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] applying pattern '^' to uri 'css/main.css'
[Tue Nov 18 09:24:16.238361 2014] [rewrite:trace4] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] RewriteCond: input='off' pattern='!=on' => matched 
[Tue Nov 18 09:24:16.238373 2014] [rewrite:trace4] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] RewriteCond: input='apache.h5bp.dev:81' pattern='^www\\.(.+)$' [NC] => not-matched
[Tue Nov 18 09:24:16.238383 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.css -> css/main.css
[Tue Nov 18 09:24:16.238393 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] applying pattern '(^|/)\\.' to uri 'css/main.css'
[Tue Nov 18 09:24:16.238410 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] strip per-dir prefix: /var/www/html5-boilerplate/css/main.css -> css/main.css
[Tue Nov 18 09:24:16.238421 2014] [rewrite:trace3] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] applying pattern '^(.+)\\.(\\d+)\\.(css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$' to uri 'css/main.css'
[Tue Nov 18 09:24:16.238433 2014] [rewrite:trace1] [pid 10057] mod_rewrite.c(475): [client 10.10.10.1:59823] 10.10.10.1 - - [apache.h5bp.dev/sid#7fa1912fe8e8][rid#7fa1912255e0/initial/redir#1] [perdir /var/www/html5-boilerplate/] pass through /var/www/html5-boilerplate/css/main.css

Take home

Notice that the input to the !-f check is an absolute path, in-keeping with apache's docs:

The full local filesystem path to the file or script matching the request, if this has already been determined by the server at the time REQUEST_FILENAME is referenced. Otherwise, such as when used in virtual host context, the same value as REQUEST_URI. Depending on the value of AcceptPathInfo, the server may have only used some leading components of the REQUEST_URI to map the request to a file.

I don't really understand "such as when used in a virtualhost context, the same value as REQUEST_URI" - since I performed this test using a virtual host and didn't observe that behavior (Edit: Ah. that probably means referencing REQUEST_FILENAME before e.g. the DocumentRoot is known..not relevant to the question here).

Either way though, I do not recommend taking any action here as, without understanding why the path was wrong for @warrenski, changing the rule will simply break it for many other users.

@warrenski
Copy link
Author

@AD7six Thanks for the legwork Andy

This certainly is quite an odd situation. Based on Andy's evidence, I'm happy to accept that this is not an issue for everyone. However, below I'll give you the output I see on my server: first with the untouched RewriteRule config per the repo source, then with my DOCUMENT_ROOT prefix in place. Note that in both cases the specific config is being placed into the server's global httpd.conf file.

I've followed the same process as @AD7six did in his experiment, and have used the same physical files, namely:

  • /home/httpd/htdocs/main.12345.css
  • /home/httpd/htdocs/main.css

These files respectively contain the following simple style rules:

/* main.12345.css */
body {
    background-color: red;
}

and

/* main.css */
body {
    background-color: green;
}

Here's the relevant portion of my Apache httpd.conf file:

<VirtualHost *:80>
    ServerName vs9.lh.warrenski.com
    DocumentRoot "/home/httpd/htdocs"

    RewriteLog "/var/log/httpd/rewrite_log"
    RewriteLogLevel 8

    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.+)\.(\d+)\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$ $1.$3 [L]
    </IfModule>
</VirtualHost>

Restart Apache to apply the config:

apachectl restart

A request that should NOT be rewritten

Requesting a file matching the pattern that does exist:

$ curl -i http://vs9.lh.warrenski.com/main.12345.css
HTTP/1.1 200 OK
Date: Tue, 18 Nov 2014 15:36:47 GMT
Server: Apache
Last-Modified: Tue, 18 Nov 2014 15:32:55 GMT
Accept-Ranges: bytes
Content-Length: 35
Vary: Accept-Encoding,User-Agent
Content-Type: text/css

body {
    background-color: green;
}

The result is the contents of main.css. This is not correct.

The rewrite_log showed:

192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (2) init rewrite engine with requested uri /main.12345.css
192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (3) applying pattern '^(.+)\\.(\\d+)\\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$' to uri '/main.12345.css'
192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (4) RewriteCond: input='/main.12345.css' pattern='!-f' => matched
192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (2) rewrite '/main.12345.css' -> '/main.css'
192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (2) local path result: /main.css
192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (2) prefixed with document_root to /home/httpd/htdocs/main.css
192.168.2.39 - - [18/Nov/2014:17:36:47 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f379cc0/initial] (1) go-ahead with /home/httpd/htdocs/main.css [OK]

A request that should be rewritten

Requesting a file matching the pattern that does not exist:

$ curl -i http://vs9.lh.warrenski.com/main.123456.css
HTTP/1.1 200 OK
Date: Tue, 18 Nov 2014 15:37:01 GMT
Server: Apache
Last-Modified: Tue, 18 Nov 2014 15:32:55 GMT
Accept-Ranges: bytes
Content-Length: 35
Vary: Accept-Encoding,User-Agent
Content-Type: text/css

body {
    background-color: green;
}

The result is the contents of main.css. This is correct.

The rewrite_log showed:

192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (2) init rewrite engine with requested uri /main.123456.css
192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (3) applying pattern '^(.+)\\.(\\d+)\\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$' to uri '/main.123456.css'
192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (4) RewriteCond: input='/main.123456.css' pattern='!-f' => matched
192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (2) rewrite '/main.123456.css' -> '/main.css'
192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (2) local path result: /main.css
192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (2) prefixed with document_root to /home/httpd/htdocs/main.css
192.168.2.39 - - [18/Nov/2014:17:37:01 +0200] [vs9.lh.warrenski.com/sid#f06bed8][rid#f381d00/initial] (1) go-ahead with /home/httpd/htdocs/main.css [OK]

Alter Apache's RewriteCond directive

After the above tests I altered Apache's RewriteCond directive to include the DOCUMENT_ROOT prefix. Here's the relevant portion of my Apache httpd.conf file showing the change:

<VirtualHost *:80>
    ServerName vs9.lh.warrenski.com
    DocumentRoot "/home/httpd/htdocs"

    RewriteLog "/var/log/httpd/rewrite_log"
    RewriteLogLevel 8

    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
        RewriteRule ^(.+)\.(\d+)\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$ $1.$3 [L]
    </IfModule>
</VirtualHost>

Restart Apache to apply the config:

apachectl restart

Re-testing a request that should NOT be rewritten

Requesting a file matching the pattern that does exist:

$ curl -i http://vs9.lh.warrenski.com/main.12345.css
HTTP/1.1 200 OK
Date: Tue, 18 Nov 2014 15:39:55 GMT
Server: Apache
Last-Modified: Tue, 18 Nov 2014 15:32:36 GMT
Accept-Ranges: bytes
Content-Length: 33
Vary: Accept-Encoding,User-Agent
Content-Type: text/css

body {
    background-color: red;
}

The result is the contents of main.12345.css. This is now correct.

The rewrite_log showed:

192.168.2.39 - - [18/Nov/2014:17:39:55 +0200] [vs9.lh.warrenski.com/sid#f06fef8][rid#f379c60/initial] (2) init rewrite engine with requested uri /main.12345.css
192.168.2.39 - - [18/Nov/2014:17:39:55 +0200] [vs9.lh.warrenski.com/sid#f06fef8][rid#f379c60/initial] (3) applying pattern '^(.+)\\.(\\d+)\\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$' to uri '/main.12345.css'
192.168.2.39 - - [18/Nov/2014:17:39:55 +0200] [vs9.lh.warrenski.com/sid#f06fef8][rid#f379c60/initial] (4) RewriteCond: input='/home/httpd/htdocs/main.12345.css' pattern='!-f' => not-matched
192.168.2.39 - - [18/Nov/2014:17:39:55 +0200] [vs9.lh.warrenski.com/sid#f06fef8][rid#f379c60/initial] (3) applying pattern '^/(.*)$' to uri '/main.12345.css'
192.168.2.39 - - [18/Nov/2014:17:39:55 +0200] [vs9.lh.warrenski.com/sid#f06fef8][rid#f379c60/initial] (4) RewriteCond: input='/main.12345.css' pattern='^/phpmyadmin' [NC] => not-matched
192.168.2.39 - - [18/Nov/2014:17:39:55 +0200] [vs9.lh.warrenski.com/sid#f06fef8][rid#f379c60/initial] (1) pass through /main.12345.css

Conclusion

I'm stumped as to why my server's behaving differently to yours @AD7six, and I can't think of any leads to explain the difference. I'd have to concur with your recommendation not to make a change to the repo, in case it breaks it for others. Hopefully this thread will come up via a Google search and help anybody else battling with a similar problem.

@AD7six
Copy link
Member

AD7six commented Nov 18, 2014

@warrenski so what's happening is the config you're using falls into:

Otherwise, such as when used in virtual host context, the same value as REQUEST_URI

I was using a .htaccess file, and your use case is (the preferred) conf files - My first attempt to use a conf-based test showed no change but by experimenting a little I think I've figured it out.

This works:

It'll work when the rule is in a .htaccess file, or inside a directory block i.e. this config would work:

<VirtualHost *:80>
    DocumentRoot /var/www/

    <Directory /var/www/>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f 
        RewriteRule ^(.+)\.(\d+)\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$ $1.$3 [L] 
    </Directory>
</VirtualHost>

This does not work:

<VirtualHost *:80>
    DocumentRoot /var/www/

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.+)\.(\d+)\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp)$ $1.$3 [L] 
</VirtualHost>

Because: reasons.

In this case the rule is applied "in virtual host context" - hence it's the URI not an absolute file path.

There are actually quite a few tickets for this behavior in apache's bug tracker, such as this one - all stemming from the confusion created by this variable not being an absolute path sometimes.

So mystery solved. I don't know if there are other cases like this to account for - definitely something to keep in mind though.

@warrenski
Copy link
Author

@AD7six I think you've answered it then, thanks again for digging around. It's been a pleasure working through this together.

@alrra
Copy link
Member

alrra commented Nov 18, 2014

@AD7six Thanks for looking into this! 👍

@alrra alrra closed this as completed Nov 18, 2014
@AD7six
Copy link
Member

AD7six commented Nov 19, 2014

No problem - I'm quite happy to help in my selfish quest to learn and understand =).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants