web-dev-qa-db-ja.com

.htaccessリライトルールをデバッグするためのヒント

多くのポスターは、.htaccessファイル内のRewriteRuleおよびRewriteCondステートメントのデバッグに問題があります。これらのほとんどは共有ホスティングサービスを使用しているため、ルートサーバー設定にアクセスできません。 .htaccessファイルを書き換えに使用したり、RewriteLogLevelを有効にすることはできません。多くの回答者が示唆しているように、.htaccess固有の落とし穴がたくさんあります。ローカルテストのLAMPスタックは、ほとんどの人にとって学習曲線が多すぎます。

だから私のQはここに私たちは彼らがデバッグ彼らのルールをお勧めする方法です)自分自身。以下にいくつか提案します。他の提案は大歓迎です。

  1. mod_rewriteエンジンが.htaccessファイルを循環することを理解してください。エンジンはこのループを実行します。

    do
      execute server and vhost rewrites (in the Apache Virtual Host Config)
      find the lowest "Per Dir" .htaccess file on the file path with rewrites enabled
      if found(.htaccess)
         execute .htaccess rewrites (in the user's directory)
    while rewrite occurred
    

    そのため、あなたのルールは繰り返し実行され、URIパスを変更した場合、他の.htaccessファイルが存在すればそれを実行することになります。そのため、必要に応じて、ルールの実行を停止するために余分なRewriteCondを追加して、必ずこのループを終了してください。明示的にマルチレベルルールセットを使用するつもりがない限り、下位レベルの.htaccess書き換えルールセットも削除します。

  2. それぞれの正規表現の構文が正しいことを確認し、それが有効な構文であり、意図したとおりのものであることを確認します。テストURIの全範囲詳しくは 以下の答え をご覧ください。

  3. テストディレクトリにルールを段階的に構築します。「パス機能で最も深い.htaccessファイルを実行する」を使用して、別のディレクトリを設定できます。ここであなたのメインのルールを台無しにしてあなたのサイトが動くのを止めることなくここでテストディレクトリ(ツリー)とデバッグルールセット。これは、失敗を個々のルールにローカライズする唯一の方法であるため、一度に1つずつ追加する必要があります。

  4. ダミーのスクリプトスタブを使用して、サーバー変数と環境変数をダンプします。 (リスト2を参照してください。)blog/index.phpなどのアプリを使用している場合は、これをtest/blog/index.phpにコピーして、それを使用してtestのブログルールをテストできます。サブディレクトリ。また、環境変数を使用して、書き換えエンジンが置換文字列を正しく解釈するようにすることもできます。

    RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]
    

    そして、phpinfoダンプでこれらのREDIRECT _ *変数を探します。ところで、私はこれを使い、私のサイトで代わりに%{ENV:DOCUMENT_ROOT_REAL}を使わなければならないことを発見しました。リダイレクタループの場合、REDIRECT_REDIRECT _ *変数は前のパスをリストします。等..

  5. あなたのブラウザが301の間違ったリダイレクトをキャッシュしていることに噛まれないように気をつけてください下記の答え を参照してください。 lrich Palha に感謝します。

  6. 書き換えエンジンは.htaccessコンテキスト内のカスケードされたルールに敏感です(つまり、RewriteRuleは置換になりますが、これは他のルールにも当てはまります)。内部のサブリクエストにバグがあることがわかりました (1) =、および誤ったPATH_INFO処理は、[NS]、[L]、および[PT]フラグを使用することで防止できます。

もうコメントや提案がありますか?

リスト1 - phpinfo

<?php phpinfo(INFO_ENVIRONMENT|INFO_VARIABLES);
260
TerryE

共有ホスティングを使用しているユーザーのデバッグを容易にするための、テストルールに関するヒントをいくつか紹介します。

1.偽のユーザーエージェントを使う

新しいルールをテストするときは、リクエストに使用するfakeユーザーエージェントでのみ実行する条件を追加します。このようにして、あなたのサイトの他の誰にも影響を与えません。

例えば

#protect with a fake user agent
RewriteCond %{HTTP_USER_AGENT}  ^my-fake-user-agent$
#Here is the actual rule I am testing
RewriteCond %{HTTP_Host} !^www\.domain\.com$ [NC] 
RewriteRule ^ http://www.domain.com%{REQUEST_URI} [L,R=302] 

Firefoxを使用している場合は、偽のユーザーエージェント文字列を作成してテストするために ser Agent Switcher を使用できます。

2.テストが終わるまで301を使用しないでください

私は人々がまだ彼らのルールをテストしていて、彼らが301のものを使用しているところで非常に多くの投稿を見ました。 いけません

あなたがあなたのサイトで提案1を使用していない場合は、あなただけではなく、その時点であなたのサイトを訪れた誰もが301の影響を受けることになります。

それらは永続的で、あなたのブラウザによって積極的にキャッシュされていることを忘れないでください。確実になるまで代わりに302を使用し、それを301に変更してください。

3. 301はあなたのブラウザに積極的にキャッシュされていることを忘れないでください

あなたのルールがうまくいかず、それがあなたにとって正しいように見え、そしてあなたが提案1と2を使用していなかったら、そしてあなたのブラウザキャッシュをクリアした後またはプライベートブラウジングの間に再テストしなさい。

4. HTTPキャプチャツールを使用する

ブラウザとサーバー間の実際のHTTPトラフィックを確認するには、 Fiddler のようなHTTPキャプチャツールを使用します。

他の人があなたのsite does not look rightと言っているかもしれませんが、代わりにそのall of the images, css and js are returning 404 errorsを見て報告することで、問題をすぐに絞り込むことができます。

他の人があなたがstarted at URL A and ended at URL Cだと報告する一方で、あなたは彼らがURL A, were 302 redirected to URL B and 301 redirected to URL Cで始まったことを見ることができるでしょう。たとえURL Cが最終目標であったとしても、これはSEOには良くないので修正する必要があることがわかります。

あなたは、サーバ側で設定されたキャッシュヘッダを見て、リクエストを再生し、テストするためにリクエストヘッダを修正することができます。


126
Ulrich Palha

オンライン.htaccessリライトテスト

this RegExヘルプのためのグーグル、私が少し修正を加えるたびに新しい.htaccessファイルをアップロードしなければならないことから多くの時間を節約しました。

サイトから:

htaccessテスター

Htaccessの書き換えルールをテストするには、ルールを適用しているURLを入力し、htaccessの内容をより大きな入力領域に配置して[今すぐ確認]ボタンをクリックします。

73
JCastell

.htaccessファイルでは、一致する相対URLであることを忘れないでください。

.htaccessファイルでは、次のRewriteRuleは決して一致しません。

RewriteRule ^/(.*)     /something/$s
12

各正規表現の構文が正しいことを確認してください。

それが有効な構文であることを確認するために一連のテストパターンに対してテストすることによって、そしてあなたが意図することを完全な範囲のテストURIで行うこと。

あなたがこれをするのを助けるためにあなたのサイトの中のprivate/testディレクトリに追加することができる簡単なスクリプトについては下記のregexpCheck.phpを参照してください。私はきれいではなく、この簡潔さを保ったこれをテストディレクトリのregexpCheck.phpファイルに貼り付けるだけで、Webサイトで使用できます。これは、正規表現を作成し、それをテストケースのリストに対してテストするのに役立ちます。ここではPHP PCREエンジンを使用していますが、Apacheのソースを調べたところ、これは基本的にApacheで使用されているものと同じです。テンプレートを提供し、あなたがあなたの正規表現のスキルを築くのを助けることができる多くのHowTosとチュートリアルがあります。

リスト1 - regexpCheck.php

<html><head><title>Regexp checker</title></head><body>
<?php 
    $a_pattern= isset($_POST['pattern']) ? $_POST['pattern'] : "";
    $a_ntests = isset($_POST['ntests']) ? $_POST['ntests'] : 1;
    $a_test   = isset($_POST['test']) ? $_POST['test'] : array();

    $res = array(); $maxM=-1; 
    foreach($a_test as $t ){
        $rtn = @preg_match('#'.$a_pattern.'#',$t,$m);
        if($rtn == 1){
            $maxM=max($maxM,count($m));
            $res[]=array_merge( array('matched'),  $m );
        } else {
            $res[]=array(($rtn === FALSE ? 'invalid' : 'non-matched'));
        }
    } 
?> <p>&nbsp; </p>
<form method="post" action="<?php echo $_SERVER['SCRIPT_NAME'];?>">
    <label for="pl">Regexp Pattern: </label>
    <input id="p" name="pattern" size="50" value="<?php echo htmlentities($a_pattern,ENT_QUOTES,"UTF-8");;?>" />
    <label for="n">&nbsp; &nbsp; Number of test vectors: </label>
    <input id="n" name="ntests"  size="3" value="<?php echo $a_ntests;?>"/>
    <input type="submit" name="go" value="OK"/><hr/><p>&nbsp;</p>
    <table><thead><tr><td><b>Test Vector</b></td><td>&nbsp; &nbsp; <b>Result</b></td>
<?php 
    for ( $i=0; $i<$maxM; $i++ ) echo "<td>&nbsp; &nbsp; <b>\$$i</b></td>";
    echo "</tr><tbody>\n";
    for( $i=0; $i<$a_ntests; $i++ ){
        echo '<tr><td>&nbsp;<input name="test[]" value="', 
            htmlentities($a_test[$i], ENT_QUOTES,"UTF-8"),'" /></td>';
        foreach ($res[$i] as $v) { echo '<td>&nbsp; &nbsp; ',htmlentities($v, ENT_QUOTES,"UTF-8"),'&nbsp; &nbsp; </td>';}
        echo "</tr>\n";
    }
?> </table></form></body></html>
8
TerryE

私が無駄にした数時間からの1つ:

これらすべてのヒントを適用しても、サーバーのエラーログにアクセスできないために500エラーしか発生していない場合は、問題は.htaccessファイルではなくリダイレ​​クト先のファイルにある可能性があります。

.htaccess-problemを修正した後、単にいくつかの権限を忘れていたにもかかわらず、さらに2時間かけてそれを修正しようとしました。

6
Ruben

環境変数を設定し、それらを受け取るためにヘッダーを使用します。

OPで説明されているように、RewriteRule行を使って新しい環境変数を作成できます。

RewriteRule ^(.*) - [E=TEST0:%{DOCUMENT_ROOT}/blog/html_cache/$1.html]

しかし、サーバーサイドのスクリプトを動作させることができない場合は、どうすればこの環境変数を読み取ることができますか? 1つの解決策はヘッダを設定することです。

Header set TEST_FOOBAR "%{REDIRECT_TEST0}e"

フォーマット指定子を受け付ける 、環境変数の%{NAME}e指定子を含みます(小文字のeを忘れないでください)。時々、あなたはREDIRECT_接頭辞を追加する必要があるでしょう、しかし私は接頭辞が追加されるときと追加されないときにうまくいきませんでした。

6
Flimm

必ずドル記号ではなく、パーセント記号を変数の前に使用してください。

%{HTTP_Host}not${HTTP_Host}です。 error_logには何もないでしょう、内部サーバーエラーはないでしょう、あなたの正規表現はまだ正しい、規則はちょうど一致しません。 Django/genshiテンプレートをたくさん使っていて、マッスルメモリの変数置換のために${}を持っているなら、これは本当に恐ろしいことです。

5
Simon

リダイレクトを作成している場合は、ブラウザのキャッシュの問題を回避するために curl でテストしてください。 httpヘッダのみを取得するには、-Iを使用します。すべてのリダイレクトに従うには、-Lを使用してください。

4
flm

4.に関しては、あなたはまだあなたの "ダミースクリプトスタブ"がすべての書き換えが行われた後に実際にターゲットURLであることを確認する必要があります、さもなければあなたは何も見ないでしょう!

似たような/関連するトリック( この質問 を参照)は、次のような一時的な規則を挿入することです。

RewriteRule (.*) /show.php?url=$1 [END]

show.phpは、その$_GETパラメータを表示するだけの非常に単純なスクリプトです(必要に応じて環境変数も表示できます)。

これにより、デバッガのブレークポイントのように、ルールセットに挿入した時点で書き換えが停止します。

Apache <2.3.9を使用している場合、[L]ではなく[END]を使用する必要があります。そしてあなたはを追加する必要があります。

RewriteRule ^show.php$ - [L]

あなたのルールセットの一番上で、ifの場合、URL /show.phpはそれ自身書き換えられています。

3
Doin

私のmod_rewrite問題をデバッグしようとしているときに私はこの質問を見つけました、そしてそれは間違いなくいくつかの役に立つアドバイスを持っています。しかし最後に最も重要なことは、正規表現の構文が正しいことを確認することです。私自身のRE構文の問題により、regexpCheck.phpスクリプトをインストールすることは現実的ではありませんでした。

しかし、ApacheはPerl互換の正規表現(PCRE)を使っているので、PCREを書くのを手助けするどんなツールでも助けになるはずです。私は過去にRegexPlanetのツールをJavaとJavascriptのREと一緒に使ったことがあり、それらがPerlもサポートしていることを嬉しく思いました。

正規表現と1つ以上のURLの例を入力するだけで、正規表現が一致するか(「〜=」列に「1」)、該当する場合は一致するグループ(「分割」の番号)が表示されます。列はApacheが期待する数字に対応します(例:各URLに対して$ 1、$ 2など)。彼らは、PCREサポートは「ベータ版」であると主張していますが、それは私が構文上の問題を解決するために必要なものでした。

http://www.regexplanet.com/advanced/Perl/index.html

既存の回答に単にコメントを追加しただけでしたが、私の評判はまだそのレベルにはありません。これが誰かに役立つことを願っています。

3
Lambart

私が観察したいくつかの間違いは.htaccessを書くときに起こります

複数のルールで^(.*)$を繰り返し使用し、^(.*)$を使用すると、ほとんどの場合他のルールが無力になります。これは、1回のヒットですべてのURLが一致するためです。

したがって、このur_sapmle/urlにルールを使用している場合は、このur_sapmle/url/stringも消費します。


[L] フラグを使用して、ルールが処理を完了したことを確認してください。


知っておくべきこと:

%nと$ nの違い

%n%{RewriteCond}部分で一致し、$n%{RewriteRule}部分で一致します。

RewriteBaseの働き

RewriteBaseディレクティブは、相対パスを置き換えるディレクトリごと(htaccess)のRewriteRuleディレクティブに使用されるURLプレフィックスを指定します。

このディレクティブは、以下の条件のいずれにも該当しない限り、ディレクトリーごと(htaccess)のコンテキストで置換に相対パスを使用する場合に必要です。

元の要求と置換は、(Aliasなどの他の手段で到達可能ではなく)DocumentRootの下にあります。相対的な置換が後に続くRewriteRuleを含むディレクトリへのファイルシステムパスは、サーバー上のURLパスとしても有効です(これはまれです)。 Apache HTTPサーバ2.4.16以降では、リクエストがAliasまたはmod_userdirを介してマッピングされるときは、このディレクティブは省略されるかもしれません。

2
Abhishek Gurjar

.htacesssに1行以上の規則を書くことを計画しているなら、
これらのホットフィックス方法の1つを使ってデバッグすることさえ考えないでください。

LOGからのフィードバックなしに複数のルールを設定することに何日も無駄にしていましたが、最終的に1つをあきらめることになりました。
私は自分のPCにApacheをインストールし、サイト全体をHDDにコピーし、そしてルールセット全体をログを使って本当に速く整理しました。
それから私は働いていた私の古い規則を見直しました、私は彼らが本当に望まれたことをしていないのを見ました。少し違う住所の時限爆弾。

書き換え規則には非常に多くの落とし穴がありますが、それはまったく論理的なことではありません。
Apacheを10分で立ち上げることができます。インストールしなくても10MB、良いライセンス、* NIX/WIN/MAC対応です。
また、あなたのサーバのヘッダ行をチェックし、古いバージョンならばアーカイブから同じバージョンのApacheを入手してください。私のOPはまだ2.0です、多くのことはサポートされていません。

1
papo

(Doinのアイデアに似ています)何がマッチしているのかを示すために、私はこのコードを使います

$keys = array_keys($_GET);
foreach($keys as $i=>$key){
    echo "$i => $key <br>";
}

サーバルートのr.phpに保存してから、.htaccessでいくつかのテストを行います。
たとえば、言語プレフィックスで始まらないURLを照合したい

RewriteRule ^(?!(en|de)/)(.*)$ /r.php?$1&$2 [L] #$1&$2&...
RewriteRule ^(.*)$ /r.php?nomatch [L] #report nomatch and exit
0
UnLoCo

ここにこれを残します、おそらく詳細ですが、何時間も頭を叩きました:%{REQUEST_URI}の使用には注意してください:彼の答えで @ Krist van Besien が完全に正しいので、 REQUEST_URI文字列の場合はそうではありません。これは、このTestStringの出力が/で始まるためです。だから注意してください:

RewriteCond %{REQUEST_URI} ^/assets/$  
                            ^
                            | check this pesky fella right here if missing
0
Gruber