Apache でリダイレクト、URL の変更、または HTTP を HTTPS にリダイレクトする - mod_rewrite ルールについて知りたいことすべて、でも聞くのが怖かったこと

Apache でリダイレクト、URL の変更、または HTTP を HTTPS にリダイレクトする - mod_rewrite ルールについて知りたいことすべて、でも聞くのが怖かったこと

これは標準的な質問Apache の mod_rewrite について。

リクエスト URL を変更したり、ユーザーを最初にリクエストした URL とは別の URL にリダイレクトしたりするには、mod_rewrite を使用します。これには次のようなことが含まれます。

  • HTTP を HTTPS に変更する (またはその逆)
  • 存在しなくなったページへのリクエストを新しいページに変更します。
  • URL 形式の変更 (?id=3433 を /id/3433 に変更するなど)
  • ブラウザ、リファラー、月と太陽の下で可能なあらゆるものに基づいて、異なるページを表示します。
  • URLでいじりたいもの

Mod_Rewrite ルールについて知りたいことすべて、でも聞くのが怖かったこと!

mod_rewrite ルールの作成の専門家になるにはどうすればよいですか?

  • mod_rewrite ルールの基本的な形式と構造は何ですか?
  • どのような形式/種類の正規表現をしっかりと理解する必要がありますか?
  • 書き換えルールを書くときに最もよくある間違いや落とし穴は何ですか?
  • mod_rewrite ルールをテストおよび検証するための適切な方法は何ですか?
  • mod_rewrite ルールには SEO やパフォーマンスへの影響があるかどうか知っておく必要がありますか?
  • mod_rewrite が適切なツールのように見えるが、実際にはそうではないという一般的な状況はありますか?
  • よくある例にはどのようなものがありますか?

自分のルールをテストする場所

htaccess テスターこの Web サイトは、ルールを試してテストするのに最適な場所です。デバッグ出力も表示されるので、何が一致し、何が一致しなかったかを確認できます。

答え1

mod_rewrite 構文の順序

mod_rewrite には、処理に影響する特定の順序付けルールがあります。何かを実行する前に、RewriteEngine Onmod_rewrite 処理を有効にするディレクティブを指定する必要があります。これは、他の書き換えディレクティブよりも前に指定する必要があります。

RewriteCond前述RewriteRuleの 1 つのルールが条件の対象になります。後続の RewriteRule は、条件の対象ではないものとして処理されます。

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html

この単純なケースでは、HTTP リファラーが serverfault.com からのものである場合、ブログのリクエストを特別な serverfault ページにリダイレクトします (私たちはそれほど特別です)。ただし、上記のブロックに追加の RewriteRule 行があった場合:

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html
RewriteRule $/blog/(.*)\.jpg         $/blog/$1.sf.jpg

すべての .jpg ファイルは、ここから来たことを示すリファラを持つファイルだけでなく、特別な serverfault ページに移動します。これは、これらのルールの記述方法の意図ではありません。複数の RewriteCond ルールを使用して実行できます。

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

しかし、おそらく、よりトリッキーな置換構文を使用して実行する必要があります。

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

より複雑な RewriteRule には、処理の条件が含まれています。最後の括弧は、 RewriteRule に またはのいずれ(html|jpg)かに一致し、一致した文字列を書き換えられた文字列の $2 として表すように指示します。これは、2 つの RewriteCond/RewriteRule ペアを持つ前のブロックと論理的に同一ですが、4 行ではなく 2 行で実行されます。htmljpg

複数の RewriteCond 行は暗黙的に AND 結合され、明示的に OR 結合できます。ServerFault と Super User の両方からの参照を処理するには (明示的な OR)、次のようにします。

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)    [OR]
RewriteCond %{HTTP_REFERER}                ^https?://superuser\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

ServerFault が参照したページを Chrome ブラウザで提供するには (暗黙的な AND):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteCond %{HTTP_USER_AGENT}             ^Mozilla.*Chrome.*$
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

RewriteBaseは、後続のディレクティブがどのように処理するかを指定するため、順序も指定されますRewriteRule。これは、.htaccess ファイルで非常に便利です。使用する場合は、.htaccess ファイルの「RewriteEngine on」の下の最初のディレクティブにする必要があります。次の例をご覧ください。

RewriteEngine On
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

これはmod_rewriteに、現在処理しているこの特定のURLが次の方法で到着したことを伝えています。http://example.com/blog/物理ディレクトリ パス (/home/$Username/public_html/blog) の代わりに、それに応じて処理します。このため、 は、RewriteRule文字列の開始が URL 内の "/blog" の後にあるとみなします。次に、同じ内容を 2 つの異なる方法で記述します。1 つは RewriteBase あり、もう 1 つは RewriteBase なしです。

RewriteEngine On

##Example 1: No RewriteBase##
RewriteCond %{HTTP_REFERER}                                   ^https?://serverfault\.com(/|$)
RewriteRule /home/assdr/public_html/blog/(.*)\.(html|jpg)     $1.sf.$2

##Example 2: With RewriteBase##
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

ご覧のとおり、RewriteBase書き換えルールはWebを活用できます。サイトウェブではなくコンテンツへの道サーバこれにより、そのようなファイルを編集する人にとって、より分かりやすくなります。また、ディレクティブを短くすることができ、見た目も良くなります。


RewriteRule マッチング構文

RewriteRule自体には、文字列を一致させるための複雑な構文があります。フラグ([PT]など)については別のセクションで説明します。システム管理者は、マニュアルを読むよりも例から学ぶことが多いため、マニュアルページ例を挙げて、その機能について説明します。

RewriteRule ^/blog/(.*)$    /newblog/$1

この.*構造は、任意の 1 文字 ( .) を 0 回以上 ( *) 一致させます。括弧で囲むと、一致した文字列が $1 変数として提供されます。

RewriteRule ^/blog/.*/(.*)$  /newblog/$1

この場合、最初の .* は括弧で囲まれていないため、書き換えられた文字列には提供されません。このルールは、新しいブログ サイトのディレクトリ レベルを削除します (/blog/2009/sample.html は /newblog/sample.html になります)。

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$2

この場合、最初の括弧式は一致するグループを設定します。これは $1 になりますが、これは必要ないため、書き換えられた文字列では使用されません。

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$1/$2

この場合、書き換えられた文字列では $1 を使用します。

RewriteRule ^/blog/(20[0-9][0-9])/(.*)$   /newblog/$1/$2

このルールは、文字を指定するための特別な括弧構文を使用します。範囲. [0-9] は 0 から 9 までの数字に一致します。この特定のルールは 2000 年から 2099 年までの年を処理します。

RewriteRule ^/blog/(20[0-9]{2})/(.*)$  /newblog/$1/$2

これは前のルールと同じことを行いますが、{2} 部分は前の文字 (この場合は括弧式) を 2 回一致させるように指示します。

RewriteRule ^/blog/([0-9]{4})/([a-z]*)\.html   /newblog/$1/$2.shtml

この場合、2 番目の一致表現の任意の小文字と一致し、可能な限り多くの文字が一致します。この\.構造は、ピリオドを、前の例の特殊文字ではなく、実際のピリオドとして扱うように指示します。ただし、ファイル名にダッシュが含まれている場合は機能しません。

RewriteRule ^/blog/([0-9]{4})/([-a-z]*)\.html  /newblog/$1/$2.shtml

これはダッシュを含むファイル名をトラップします。ただし、-括弧式内の特殊文字と同様に、初め式内の文字。

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

このバージョンは、文字、数字、または-ファイル名内の文字を含むファイル名をトラップします。これは、括弧式で複数の文字セットを指定する方法です。


RewriteRule フラグ

書き換えルールのフラグには多くの特別な意味と使用例がある

RewriteRule ^/blog/([0-9]{4})/([-a-z]*).\html  /newblog/$1/$2.shtml  [L]

フラグは[L]上記の式の末尾にあります。複数のフラグをカンマで区切って使用できます。リンクされたドキュメントでは各フラグについて説明していますが、ここではその内容を説明します。

= 最後。これが一致したら、RewriteRules の処理を​​停止します。順序が重要です。
= チェーン。次の RewriteRule の処理を​​続行します。このルールが一致しない場合は、次のルールは実行されません。これについては後で詳しく説明します。
= 環境変数を設定します。Apache には、Web サーバーの動作に影響を与えるさまざまな環境変数があります。
= 禁止。このルールが一致する場合は 403-Forbidden エラーを返します。
= Gone。このルールが一致すると、410-Gone エラーが返されます。
H= ハンドラ。指定された MIME タイプであるかのようにリクエストを強制的に処理します。
いいえ= 次へ。ルールを最初からやり直して再度照合するように強制します。注意してください。ループが発生する可能性があります。
ノースカロライナ= 大文字と小文字を区別しません。jpgjpgと JPG の両方に一致できます。
北東= エスケープなし。特殊文字 (. ? # & など) が 16 進コードに書き換えられるのを防ぎます。
NS= サブリクエストはありません。サーバー側インクルードを使用している場合、これにより、インクルードされたファイルとの一致が防止されます。
= プロキシ。ルールを mod_proxy で処理するように強制します。Web サーバーがコンテンツを取得して再提供するため、他のサーバーからのコンテンツを透過的に提供します。これは危険なフラグです。不適切に記述すると、Web サーバーがオープン プロキシになり、悪影響を及ぼします。
PT= パススルー。RewriteRule のマッチングで Alias ステートメントを考慮します。
品質保証= QSAppend。元の文字列にクエリ(http://example.com/thing?asp=foo) は、書き換えられた文字列に元のクエリ文字列を追加します。通常は破棄されます。動的コンテンツにとって重要です。
R= リダイレクト。指定された URL への HTTP リダイレクトを提供します。正確なリダイレクト コード [R=303] も提供できます。 と非常に似ていますがRedirectMatch、こちらの方が高速なので、可能な場合は使用してください。
= スキップ。このルールをスキップします。
T= タイプ。返されるコンテンツの MIME タイプを指定します。AddTypeディレクティブと非常によく似ています。

これは 1 つのルールにのみ適用されると言いましたよねRewriteCond? 連鎖することでこれを回避できます。

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html     [C]
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

最初の RewriteRule には Chain フラグがあるため、2 番目の書き換えルールは最初の書き換えルールが実行されるとき、つまり前の RewriteCond ルールが一致したときに実行されます。Apache の正規表現が苦手な場合には便利です。ただし、最初のセクションで紹介したオールインワン ライン メソッドの方が、最適化の観点からは高速です。

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

これはフラグを使用することで簡単に行うことができます:

RewriteRule ^/blog/([0-9]{4})/([-0-9a-z]*)\.html   /newblog/$1/$2.shtml   [NC]

また、いくつかのフラグも RewriteCond に適用されます。特に、NoCase です。

RewriteCond %{HTTP_REFERER}        ^https?://serverfault\.com(/|$)     [NC]

「ServerFault.com」と一致します

答え2

mod_rewrite ルールの基本的な形式と構造は何ですか?

これらの点については、sysadmin1138 の優れた回答に従います。

どのような形式/種類の正規表現をしっかりと理解する必要がありますか?

sysadmin1138 によって概説された構文順序、構文マッチング/正規表現、および RewriteRule フラグに加えて、mod_rewrite は HTTP リクエスト ヘッダーと Apache の構成に基づいて Apache 環境変数を公開することにも言及する価値があると思います。

私がお勧めしますAskApache の mod_rewrite デバッグ チュートリアルmod_rewrite で使用できる変数の包括的なリスト。

書き換えルールを書くときに最もよくある間違いや落とし穴は何ですか?

RewriteRule の問題のほとんどは、PCRE 構文の誤解、特殊文字の適切なエスケープの失敗、またはマッチングに使用される変数の内容に関する洞察力の欠如に起因します。

一般的な問題と推奨されるトラブルシューティング:

  • 500内部サーバーエラー-Windows キャリッジコントロールを削除する設定ファイルが存在する場合は、mod_rewriteが有効になっていることを確認してください(ディレクティブをIfModule条件付きでこのシナリオを回避する)、ディレクティブの構文をチェックし、問題が特定されるまでディレクティブをコメントアウトする
  • リダイレクトループ- RewriteLog と RewriteLogLevel を活用し、問題が特定されるまでディレクティブをコメントアウトします。

mod_rewrite ルールをテストおよび検証するための適切な方法は何ですか?

まず、照合する予定の環境変数の内容を確認します。PHP がインストールされている場合は、アプリケーションに次のブロックを追加するだけで済みます。

<?php
  var_dump($_SERVER);
?>

...次にルールを記述し(できれば開発サーバーでテスト用)、Apacheの不一致な一致やアクティビティを書き留めます。エラーログファイル。

より複雑なルールについては、mod_rewriteのRewriteLogアクティビティをファイルに記録し、設定するためのディレクティブRewriteLogLevel 3

mod_rewrite ルールには SEO やパフォーマンスへの影響があるかどうか知っておく必要がありますか?

AllowOverride allApache は.htaccess各リクエストでファイルをチェックし、ディレクティブを解析する必要があるため、サーバーのパフォーマンスに影響します。可能であれば、サイトの VirtualHost 構成ですべてのディレクティブを保持するか、.htaccess必要なディレクトリに対してのみオーバーライドを有効にします。

Googleのウェブマスターガイドライン明示的に次のように記述します。「ユーザーを欺いたり、ユーザーに表示するコンテンツとは異なるコンテンツを検索エンジンに提示したりしないでください。これは一般に「クローキング」と呼ばれます。」 - 検索エンジン ロボットをフィルタリングする mod_rewrite ディレクティブの作成は避けてください。

検索エンジンのロボットは1:1のコンテンツ:URIマッピングを好みます(これはコンテンツへのリンクをランク付けするための基礎です) - mod_rewriteを使用して一時的なリダイレクトを作成している場合、または複数のURIで同じコンテンツを提供している場合は、正規URIHTML ドキュメント内。

mod_rewrite が適切なツールのように見えるが、実際にはそうではないという一般的な状況はありますか?

これはそれ自体が大きな(そして潜在的に論争の的となる)トピックです。使用法についてはケースバイケースで対処し、提案された解決策がニーズに適しているかどうかを質問者に判断させる方が(私見では)良いでしょう。

よくある例にはどのようなものがありますか?

AskApache の mod_rewrite のコツとヒント定期的に発生する一般的なユースケースのほぼすべてをカバーしていますが、特定のユーザーにとっての「正しい」ソリューションは、ユーザーの設定と既存のディレクティブの洗練度に依存する可能性があります(そのため、どの他のmod_rewrite の質問が発生するたびにユーザーが実行するディレクティブ)。

答え3

多くの管理者/開発者と同様に、私は何年も書き換えルールの複雑さと格闘しており、既存の Apache ドキュメントに満足していないため、個人的なプロジェクトとして、mod_rewriteApache コアの実際の動作と他の Apache コアとの相互作用を徹底的に調べることにしました。そのため、この数か月間、テスト ケースをインストルメント化し、straceソース コードを詳しく調べて、これらすべてを把握してきました。

書き換えルールの開発者が考慮する必要がある重要なコメントをいくつか示します。

  • 書き換えのいくつかの側面は、サーバー設定、仮想ホスト、ディレクトリ、.htaccess処理に共通しています。しかし
  • PerDir() 処理とは対照的に、ルート設定 (サーバー設定、仮想ホスト、ディレクトリ) では一部の処理が大きく異なります.htaccess
  • さらに悪いことに、PerDir 処理はほぼ無差別に INTERNAL REDIRECT サイクルをトリガーする可能性があるため、ルート構成要素は、このような PerDir 処理がこれをトリガーする可能性があることに注意して記述する必要があります。

このため、書き換えユーザー コミュニティを 2 つのカテゴリに分割し、完全に別個に扱う必要があると言ってもいいでしょう。

  • Apache設定へのルートアクセス権を持つユーザーこれらは通常、アプリケーション専用のサーバー/VM を持つ管理者/開発者であり、ここでのメッセージは非常にシンプルです。.htaccess可能な限りファイルの使用を避け、サーバーまたは仮想ホスト構成ですべてを実行します。開発者はデバッグを設定でき、rewrite.log ファイルにアクセスできるため、デバッグは比較的簡単です。

  • 共有ホストサービス(SHS)のユーザー

    • このようなユーザー持っている.htaccess代替手段がないため、/ Perdir 処理を 使用します。
    • さらに悪いことに、そのようなユーザーのスキル レベル (mod_rewrite の正規表現駆動型ラダー ロジックの使用に関する限り) は、経験豊富な管理者よりも一般的に大幅に低くなります。
    • Apache とホスティング プロバイダーは、デバッグ/診断サポートを提供していません。唯一の診断情報は、成功したリダイレクト、間違った URI へのリダイレクト、または 404/500 ステータス コードです。これにより、プロバイダーは混乱し、無力になります。
    • Apache は、このユースケースで書き換えがどのように機能するかについての説明が非常に不十分です。たとえば、どの PerDir.htaccessファイルが選択されるか、またその理由について明確な説明がありません。PerDir 循環の複雑さやこれを回避する方法についても説明されていません。

おそらく第 3 のコミュニティが存在するでしょう。それは、両方の陣営に足を踏み入れることになり、上記の結果に苦しむことになる SHS プロバイダーの管理スタッフとサポート スタッフです。

私はいくつかの記事形式のブログ記事を書いています(例:.htaccess ファイルでの Rewrite ルールの使用についての詳細) には多くの詳細な点が網羅されていますが、ここでは繰り返しません。私は独自の共有サービスと、専用の VM FLOSS プロジェクトをサポートしています。私は SHS アカウントのテスト手段として標準の LAMP VM を使い始めましたが、最終的には適切なミラー VM (ここ)。

しかし、管理者コミュニティがユーザーをどのようにサポートすべきかという点では.htaccess、次のものを開発し、提供する必要があると感じています。

  • PerDir処理における書き換えシステムが実際にどのように動作するかについての一貫した説明
  • .htaccess書き換えルールの書き方に関するガイドライン/ベストプラクティスのセット
  • シンプルなウェブベースの書き換えスクリプトパーサー。W3C HTMLパーサーに似ていますが、ユーザーはテストURIまたはテストベクターを入力して、書き換えロジックフローのログを即座に取得できます。
  • ルールから組み込み診断を取得する方法に関するヒント(例:

    • バックリファレンス ($N または %N) を拡張して、ターゲット スクリプトへの診断として使用できるようにする[E=VAR:EXPR]という事実を活用します。EXPR
    • [OR]、[C]、[SKIP]、[L]フラグを使用して書き換えルールを局所的に順序付けすると、書き換えスキーム全体が機能するようになります。それなし内部リダイレクトを利用する必要がない場合は、ループの煩わしさをすべて回避するために、次のルールをルール 1 として追加できます。

      RewriteCond %{ENV:REDIRECT_STATUS} !=""
      RewriteRule .  -  [L]
      

答え4

書き換えルールを書くときに最もよくある間違いや落とし穴は何ですか?

本当に陥りやすい落とし穴は、URLを書き換えて見かけ上のパスを変更する場合です。たとえば、 から へ /base/1234/index.html/base/script.php?id=1234スクリプトの場所への相対パスを持つ画像やCSSは、クライアントでは見つけられません。これを解決するためのいくつかのオプションは、このFAQ

関連情報