Reputation: 40038
We are using an .htaccess in combination with anchor tags to serve files and conceal the server directory structure.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /_docu/clients/$1/$2/$3.pdf [NC,L]
For example, all files are stored under /public_html/_docu/clients/
and inside that folder are listed all the clients, and then under each client their projects. However, an anchor tag for a file would read only:
http://mydomain.com/client-name/proj-name/docname.pdf
(the /_docu/clients/ being omitted - there is a good reason for this). The above .htaccess grabs the client-name
, proj-name
and docname
and serves it from the correct folder:
http://mydomain.com/_docu/clients/client-name/proj-name/docname.pdf
whilst preserving in the address bar the incorrect (concealed) directory structure.
I wish to handle the error condition of a document not existing. This should never happen, but it could. Can anyone suggest a way of dealing with this? Can something functionally akin to "if fileexist($1/$2/%3.pdf)" be somehow constructed in an .htaccess file?
EDIT:
Delayed response as JL's answer below required research and experimentation. Thanks, Jon, for the gentle push in the right direction but I haven't got it to work just yet. Here's what I tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteRule ^(.*)$ /errors/404.php [L]
I thought that what that should do is:
http://mydomain.com/_docu/clients/$1/$2/$3.pdf
does not exist,http://mydomain.com/errors/404.php
Actual outcome is an "internal server error" message.
EDIT TWO:
Latest changes:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_data/cli/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_data/cli/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.*)$ /metshare/404.php [L]
The problem with this one is that legitimate pages also are directed to 404.php
MESSAGE TO FUTURE READERS:
All of the above concerns were addressed in Jon Lin's final answer. As issues were detected, he modified his answer until it was a perfect, working solution. I am leaving the above as it is because there are some good ULOs within (unscheduled learning opportunities) for those who want to compare versions.
Upvotes: 0
Views: 896
Reputation: 143866
You need to use a condition like this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
So that your rules looks ssomething like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
RewriteRule ^ /_docu/clients%{REQUEST_URI} [L]
EDIT: Response to edit in question
You can't do this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
Because the backreferences for $1/$2/$3 don't exist yet, they are matched in the groupings in your RewriteRule
, which hasn't happened yet at this point. But you can try something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /errors/404.php [L]
Essentially creating a match against %{REQUEST_URI}
in a previous RewriteCond
then using the %N
backreferences in the following RewriteCond
.
Upvotes: 1