RewriteRule doesn't work for a CSS file and a document when a RewriteCondition is added to test if a name value parameter is in the query string
.htaccess files are extremely useful in many cases for users who either do not have root permissions or for users who simply aren't comfortable in making changes in their web server's configuration file. Trying to debug .htaccess not working isn't always the easiest thing to do, however, hopefully by checking the discuss below mentioned about htaccess, apache, mod-rewrite, , .htaccess common problems as well as the troubleshooting tips, you'll have a better grasp on what you may have to modify to get your .htaccess file running smoothly.Problem :I'm trying to change the DocumentRoot to subfolder through .htaccess.
This works well...
RewriteCond %REQUEST_URI !subfolder/
RewriteRule ^(.*)$ /subfolder/$1
...however, I only want to do this when a specific query parameter (var=test) is set, so I have this:
RewriteCond %QUERY_STRING ^var=test$
RewriteCond %REQUEST_URI !subfolder/
RewriteRule ^(.*)$ /subfolder/$1
...but for some reason, this doesn't work.
Any suggestions as to what the problem could be?
UPDATE: Here is a full (simplified) example:
.htaccess
RewriteEngine on
RewriteCond %QUERY_STRING (.*(?:^|&))var=test((?:&|$).*)
RewriteCond %REQUEST_URI !sites/test/
RewriteRule ^(.*)$ /sites/test/$1
sites/test/index.php
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<p>Test</p>
</body>
</html>
sites/test/styles.css
*
color: red;
Now try loading the page with http://example.com/?var=test. The Test text should be red, but it's not.
Remove the QUERY_STRING RewriteCond line, and it works.
But I need to be able to check for the query string somehow..
Apache Virtual Host (in case it's needed)
<VirtualHost *:80>
ServerName www.example.com
ServerAdmin admin@example.com
DocumentRoot "/var/www/mainsite"
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory "/var/www/mainsite">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
For some reason, the second code block above breaks CSS file paths, and I can't figure out why...
The only difference with the second code block is that the request for your CSS file(s) won't be rewritten. Whereas it will be for the first code block. Your CSS URL does not contain the var=test URL parameter. Only the main page URL is being rewritten, that contains the URL parameter.
So, given a request for http://example.com/?var=test then /styles.css will be requested (and not rewritten), instead of /sites/test/styles.css, which would seem to be the intention.
UPDATE#1: As mentioned in comments, it probably wouldn't be practical to try and resolve this with .htaccess. The request for the CSS file is an entirely separate request. There is no concept of a "session" here (or rather "page request"). You would need to resort to cookies in order to maintain state - which adds complexity (would need to be unset for other requests) and may not be reliable. If you wanted to stay with the query string trigger then you could solve this in PHP by checking for the var=test query string and manually appending this to the CSS URL in your HTML. (Or even, appending the correct (full) URL-path to the CSS URL in your HTML - although maybe you're trying to hide the real URL path from your users, so that may not be desirable.)
For example:
<?php
$resourceQueryString = '';
if (isset($_GET['var']) && ($_GET['var'] == 'test'))
$resourceQueryString = '?var=test';
?>
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" type="text/css" href="styles.css<?=$resourceQueryString?>">
</head>
<body>
<p>Test</p>
</body>
</html>
This naturally checks for var=test anywhere in the query string, not literally just ?var=test.
However, if you have 100s of static pages then that may not be practical either.
UPDATE#2: If you did want to try the "cookie" approach in .htaccess, then you could perhaps do something like the following (untested):
RewriteEngine on
# If query string passed then set a (session) cookie...
RewriteCond %QUERY_STRING (?:^|&)var=test(?:&|$)
RewriteRule ^ - [CO=rewrite_trigger:1:.example.com]
# If no query string and a ".php" request then unset cookie
RewriteCond %QUERY_STRING !var=test
RewriteRule .php$ - [CO=rewrite_trigger:0:.example.com:-1]
# Rewrite request if query string OR cookie is set
RewriteCond %QUERY_STRING (?:^|&)var=test(?:&|$) [OR]
RewriteCond %HTTP_COOKIE rewrite_trigger=1
RewriteCond %REQUEST_URI !^/sites/test/
RewriteRule (.*) /sites/test/$1 [L]
Change .example.com to match your domain.
Bear in mind that the cookie is not readable on the request the cookie is actually set. The cookie can only be read on subsequent requests, hence the need to check for either the query string OR the cookie.
Note that this is currently untested (may test this later if I have time). In fact, thinking about it, there may be a problem with the first .php request without the query string after a .php request with the query string (as the cookie will still be set). May need an environment variable to resolve this? Or maybe check for (query string AND .php) OR (cookie AND no .php) in order to rewrite?
Comments
Post a Comment