Lito Lito - 6 months ago 18
PHP Question

Recover a cached file from .htaccess

I'm working in a simple cache system generated by php and responded from apache

.htaccess
(and in real server by nginx).

PHP creates the cache file into
public/cache/
with files like
public/cache/post/35/my-first-post.html


VirtualHost is common to all projects, on develop we haven't a VirtualHost for each project:

<VirtualHost *:80>
DocumentRoot /var/www

<Directory /var/www>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
</VirtualHost>


.htaccess
located in
/var/www/projects/current-project/public/.htaccess
should detect this cache file and return it.

DirectoryIndex index.php

<IfModule mod_rewrite.c>
Options -MultiViews

RewriteEngine On

RewriteCond cache/$1.html -f
RewriteRule ^([a-z0-9/-]+)$ cache/$1.html [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>


Url is http://localhost/projects/current-project/public/post/35/my-first-post but production server is http://domain.com/post/35/my-first-post

And rewrite log:

[Sun May 08 13:55:11.236124 2016] [rewrite:trace4] [pid 3189] mod_rewrite.c(476): [client 127.0.0.1:43494] 127.0.0.1 - - [localhost/sid#7f2d26745ae0][rid#7f2d2668e0a0/initial] [perdir /var/www/projects/current-project/public/] RewriteCond: input='cache/post/1/my-first-post.html' pattern='-f' => not-matched


File
perdir /var/www/projects/current-project/public/
+
input='cache/post/1/my-first-post.html'
=
/var/www/projects/current-project/public/cache/post/1/my-first-post.html
exists.

I don't want to set a
RewriteBase
because is dynamic for each develop environment.

How I can detect the cache file from current
.htaccess
folder?

Working nginx version:

set $cachefile "";

if ($uri ~ ^[a-z0-9/-]+$) {
set $cachefile "/cache/$uri.html";
}

if ($uri = "/") {
set $cachefile "/cache/index.html";
}

location / {
try_files $cachefile $uri $uri/ /index.php?$query_string;
}


WORKING SOLUTION thanks to @Sumurai8:

DirectoryIndex index.php

<IfModule mod_rewrite.c>
Options -MultiViews

RewriteEngine On

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]

# No request: index cache
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1#%{REQUEST_FILENAME} ^/?#(.*/public)/
RewriteCond %1/cache/index.html -f
RewriteRule ^$ cache/index.html [L,NC]

# Request: page
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1#%{REQUEST_FILENAME} ^([a-z0-9/-]+)#(.*/public)/
RewriteCond %2/cache/%1.html -f
RewriteRule ^([a-z0-9/-]+)$ cache/$1.html [L,NC]

# Catch all script and cache generator
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>


Thanks.

Answer

The -f and other similar checks work on filenames, not urls. You should first match on %{REQUEST_FILENAME}, then construct your own filename.

RewriteCond $1#%{REQUEST_FILENAME} ^([a-z0-9/-]+)#(.*/public)/
RewriteCond %2/cache/%1.html -f
RewriteRule ^([a-z0-9/-]+)$ cache/$1.html [L]

($1 is the first capture group of the rule, which contains the latter part of the cached file. In the second condition, %2 is the second capture group of the previous condition, which contains the document root + current prefix.)

Alternatively, you can blindly rewrite to the cache, and rewrite again if the cache does not exist:

RewriteCond %{REQUEST_URI} !^/cache/
RewriteRule ^([a-z0-9/-]+)$ cache/$1.html [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

In your case index.php would need to recognize the cache url, which might be troublesome.

Comments