Bug 64447

Summary: RewriteCond local file system checks (-f and others) should allow (sane) relative path resolution
Product: Apache httpd-2 Reporter: Oded Arbel <oded>
Component: mod_rewriteAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: NEW ---    
Severity: enhancement    
Priority: P2    
Version: 2.5-HEAD   
Target Milestone: ---   
Hardware: PC   
OS: Linux   

Description Oded Arbel 2020-05-17 11:34:38 UTC
When used in a per-directory context (.htaccess file), using file system checks in RewriteCond (such as -f) with relative paths causes mod_rewrite to resolve the paths relative to the current working directory of the server process instead of against the directory of the RewriteCond.

In the following examples, using Docker, we are setting up the files `file.xyz` and `index.html` in the document root, and the creating the following rules in .htaccess:

RewriteEngine On
RewriteCond file.xyz -f
RewriteRule . index.html [L]

One might expect that as `file.xyz` exists, all requests will be redirected to `index.html`, and indeed the following command does appear to behave correctly:

docker run -ti --rm --name httpd-test httpd bash -c '
sed -i -e "s/^#\(LoadModule .*rewrite\)/\1/;s/\(AllowOverride\).*/\1 All/" conf/httpd.conf;
touch htdocs/file.xyz; echo success > htdocs/index.html;
(echo "RewriteEngine On"; echo "RewriteCond file.xyz -f"; echo "RewriteRule . index.html") > htdocs/.htaccess;
cd htdocs;
httpd-foreground'

But this only works because we cd into the document root before running the server.

This, almost identical, command does not work - requests to the server will not match the rewrite rule:

docker run -ti --rm --name httpd-test httpd bash -c '
sed -i -e "s/^#\(LoadModule .*rewrite\)/\1/;s/\(AllowOverride\).*/\1 All/" conf/httpd.conf;
touch htdocs/file.xyz; echo success > htdocs/index.html;
(echo "RewriteEngine On"; echo "RewriteCond file.xyz -f"; echo "RewriteRule . index.html") > htdocs/.htaccess;
httpd-foreground'

I believe it is not OK to expect the website creator to know in which directory the httpd process was executed and to adapt the mod_rewrite rules to that. Also, due to (I guess) security constraints, using relative URLs will never work if the server process current working directory is not somewhere under the document root.
Comment 1 Eric Covener 2020-05-17 11:49:15 UTC
> using relative URLs will never work if the server process current working 
> directory is not somewhere under the document root.

Do you mean here still relative paths in the -f/-d tests?  There are facilities for relative URLs and paths in the actual substitutions that use e.g. CONTEXT_DOCUMENT_ROOT or RewriteBase.

I think what you propose for the -d/-f would require opt-in to be suitable  for release.  At that point I am not sure if just providing a variable for the htaccess path is better and using it in some examples.

(special care would be needed for rewrite inside other config sections)
Comment 2 Oded Arbel 2020-05-17 12:20:22 UTC
1. As mod_rewrite internally calculates the directory of the .htaccess and uses it, I think that it would be great to expose that to the configuration language. This would allow us to stop using weird tricks like documented here - https://stackoverflow.com/questions/21062290 - and instead just directly ask the questions we want answered.

2. CONTEXT_DOCUMENT_ROOT is different than document root only in very specific conditions and require server-level configuration - completely out of scope from people writing .htaccess files. RewriteBase assumes that the application writer knows the full path from the document root to the application, which is often not the case when a less technical user downloads an open source application - see the above StackOverflow link for some context. I'm not familiar with any way to resolve relative paths without access to server configuration or pre-knowledge of the path structure of the website - both kind of negate the need for relative paths.

3. Because the current relative path resolution behavior in mod_rewrite is completely unexpected and unreliable in the scope of .htaccess, and also can never expected to work in common configurations (such as under Debian and Fedora/RedHat where httpd is run with cwd set to /), I don't believe there is existing setups that rely on the current behavior. That being said, if the behavior suggested in this report can be triggered by a RewriteOption, that would be good enough.