web-dev-qa-db-ja.com

名前値パラメーターがクエリ文字列にあるかどうかをテストするためにRewriteConditionが追加された場合、RewriteRuleはCSSファイルとドキュメントに対して機能しません

.htaccessを使用してDocumentRootをsubfolderに変更しようとしています。

これはうまくいきます...

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

...ただし、特定のクエリパラメータ(var=test)が設定されている場合にのみこれを実行したいので、次のようにします。

RewriteCond %{QUERY_STRING} ^var=test$
RewriteCond %{REQUEST_URI} !subfolder/
RewriteRule ^(.*)$ /subfolder/$1

...しかし、何らかの理由で、これは機能しません。

問題が何であるかについての提案はありますか?


更新:完全な(簡略化された)例です:

.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;
}

http://example.com/?var=testでページをロードしてみてください。 Testテキストは赤である必要がありますが、赤ではありません。

QUERY_STRING RewriteCond行を削除すると、機能します。

しかし、どういうわけかクエリ文字列をチェックできる必要があります。

Apache Virtual Host(必要な場合)

<VirtualHost *:80>

      ServerName www.example.com
      ServerAdmin [email protected]

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

なんらかの理由で、上の2番目のコードブロックはCSSファイルのパスを壊しますが、その理由はわかりません...

2番目のコードブロックとの唯一の違いは、CSSファイルの要求が書き換えられないことです。一方、最初のコードブロックになります。 CSS URLにvar=test URLパラメーターが含まれていません。 URLパラメータを含むメインページURLのみが書き換えられています。

そのため、http://example.com/?var=testのリクエストが与えられると、/styles.cssの代わりに/sites/test/styles.cssがリクエストされます(書き換えられません)。


PDATE#1:コメントで述べたように、おそらく.htaccessでこれを解決しようとするのは実用的ではないでしょう。 CSSファイルのリクエストは完全に別のリクエストです。ここには「セッション」(または「ページ要求」)の概念はありません。状態を維持するためにCookieを使用する必要があります。これにより、複雑さが増し(他の要求に対して設定を解除する必要があります)、信頼性がなくなる場合があります。クエリ文字列triggerを使い続けたい場合は、PHPでvar=testをチェックすることでこれを解決できます。クエリ文字列を入力し、これをHTMLのCSS URLに手動で追加します。 (あるいは、正しい(完全な)URLパスをHTMLのCSS URLに追加します-ユーザーから実際のURLパスを隠そうとしているので、望ましくない場合があります。)

例えば:

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

これは、文字通り単にvar=testではなく、クエリ文字列の任意の場所で?var=testを自然にチェックします。

ただし、数百の静的ページがある場合、それも実用的ではありません。


PDATE#2:.htaccessで "cookie"アプローチを試したい場合は、おそらく次のような(テストされていない)ことができます。

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]

ドメインに合わせて.example.comを変更します。

Cookieが実際に設定されているリクエストでは、Cookieが読み取れないことに注意してください。 Cookieは後続のリクエストでのみ読み取ることができるため、クエリ文字列OR Cookieを確認する必要があります。

これは現在テストされていないことに注意してください(時間があれば、後でテストするかもしれません)。実際、それについて考えると、最初の.phpリクエストに問題があるかもしれませんwithout.phpの後のクエリ文字列要求withクエリ文字列(Cookieは引き続き設定されるため)これを解決するには、環境変数が必要な場合がありますか?または、(クエリ文字列AND .php)OR(Cookie AND .phpなし)を書き換えて確認することもできますか?

4
MrWhite