Mobile app version of vmapp.org
Login or Join
Debbie626

: 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 I'm trying to change the DocumentRoot to subfolder

@Debbie626

Posted in: #Apache #Htaccess #ModRewrite

I'm trying to change the DocumentRoot to subfolder through .htaccess.

This works well...

RewriteCond %{REQUEST_URI} !subfolder/
RewriteRule ^(.*)$ /subfolder/


...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/


...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/


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 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 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>

10.01% popularity Vote Up Vote Down


Login to follow query

More posts by @Debbie626

1 Comments

Sorted by latest first Latest Oldest Best

 

@Ogunnowo487

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 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/ [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?

10% popularity Vote Up Vote Down


Back to top | Use Dark Theme