web-dev-qa-db-ja.com

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 tester Webサイトは、ルールをいじってテストするのに最適な場所です。デバッグ出力も表示されるので、何が一致し、何が一致しなかったかを確認できます。

268
Kyle Brandt

mod_rewrite構文の順序

mod_rewriteには、処理に影響を与える特定の順序付けルールがいくつかあります。何かを行う前に、mod_rewrite処理をオンにするため、RewriteEngine Onディレクティブを指定する必要があります。これは、他の書き換えディレクティブの前にある必要があります。

RewriteCond先行するRewriteRuleは、その1つのルールを条件付きにします。後続のRewriteRulesは、条件付きであるかのように処理されます。

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

複数のRewriteCond行は暗黙的にAND演算され、明示的にOR演算できます。 ServerFaultとスーパーユーザーの両方からのリファラーを処理するには(明示的OR):

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

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

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

これは、現在処理しているこの特定のURLが、物理ディレクトリパス(/ home/$ Username/public_html/blog)ではなく http://example.com/blog/ として到着したことをmod_rewriteに伝えています。 )、それに応じてそれを扱います。このため、RewriteRuleは、string-startがURLの「/ blog」の後にあると見なします。同じものが2つの異なる方法で書かれています。 1つはRewriteBaseを使用し、もう1つは以下を使用しません。

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 -serverではなく、web -siteコンテンツへのパスを利用できるため、よりわかりやすくなります。そのようなファイルを編集する人に。また、指令を短くすることができ、審美的な魅力があります。


RewriteRuleマッチング構文

RewriteRule自体には、文字列を照合するための複雑な構文があります。フラグ([PT]など)については、別のセクションで説明します。システム管理者は man-page を読むよりも例で学ぶことが多いため、例を挙げてそれらが何をするかを説明します。

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

このルールは、文字rangeを指定する特別なブラケット構文を使用します。 [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

これは、ダッシュを含むファイル名をトラップします。ただし、-はブラケット式の特殊文字であるため、式ではfirst文字である必要があります。

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]です。複数のフラグをコンマで区切って使用できます。リンクされたドキュメントはそれぞれについて説明しますが、ここではとにかくそれらは:

[〜#〜] l [〜#〜]=最後。これが一致したら、RewriteRulesの処理を停止します。注文数!
[〜#〜] c [〜#〜]=チェーン。次のRewriteRuleの処理を続行します。このルールが一致しない場合、次のルールは実行されません。これについては後で詳しく説明します。
[〜#〜] e [〜#〜]=環境変数を設定します。 Apacheには、Webサーバーの動作に影響を与える可能性のあるさまざまな環境変数があります。
[〜#〜] f [〜#〜]=禁止されています。このルールが一致する場合、403-Forbiddenエラーを返します。
[〜#〜] g [〜#〜]=終了しました。このルールが一致する場合、410-Goneエラーを返します。
[〜#〜] h [〜#〜]=ハンドラ。指定されたMIMEタイプであるかのように要求を強制的に処理します。
[〜#〜] n [〜#〜]=次。ルールをもう一度最初からやり直して、再照合します。注意してください!ループが発生する可能性があります。
[〜#〜] nc [〜#〜]=大文字小文字は区別されません。 jpgがjpgとJPGの両方に一致することを許可します。
[〜#〜] ne [〜#〜]=エスケープなし。特殊文字(。?#&など)を対応する16進コードに書き換えないようにします。
[〜#〜] ns [〜#〜]=サブリクエストなし。 server-side-includesを使用している場合、これにより、インクルードされたファイルとの一致が防止されます。
[〜#〜] p [〜#〜]=プロキシ。ルールをmod_proxyで強制的に処理します。他のサーバーからコンテンツを透過的に提供します。これは、ウェブサーバーがコンテンツをフェッチして再予約するためです。これは危険なフラグです。不適切に記述されていると、Webサーバーがオープンプロキシになり、それは悪いことです。
[〜#〜] pt [〜#〜]=パススルー。 RewriteRuleマッチングでエイリアスステートメントを考慮します。
[〜#〜] qsa [〜#〜]= QSAppend。元の文字列にクエリが含まれている場合( http://example.com/thing?asp=foo )元のクエリ文字列を書き換えられた文字列に追加します。通常は破棄されます。動的コンテンツにとって重要です。
[〜#〜] r [〜#〜]=リダイレクト。指定されたURLへのHTTPリダイレクトを提供します。正確なリダイレクトコードを提供することもできます[R = 303]。 RedirectMatchと非常によく似ています。これはより高速で、可能な場合に使用する必要があります。
[〜#〜] s [〜#〜]=スキップします。このルールをスキップします。
[〜#〜] t [〜#〜]=タイプ。返されるコンテンツのMIMEタイプを指定します。 AddTypeディレクティブとよく似ています。

RewriteCondは1つのルールにのみ適用されると言ったのを知っていますか?まあ、あなたは連鎖することでそれを回避することができます。

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

最初のRewriteRuleにはチェーンフラグがあるため、2番目のrewrite-ruleは、最初の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」に一致します

224
sysadmin1138

mod_rewriteルールの基本的なフォーマットと構造は何ですか?

これらの点については、sysadmin1138の優れた答えを採用します。

正規表現のどのような形式/フレーバーをしっかりと把握する必要がありますか?

Sysadmin1138で概説されている構文の順序、構文の一致/正規表現、およびRewriteRuleフラグに加えて、mod_rewriteがHTTPリクエストヘッダーとApacheの構成に基づいてApache環境変数を公開していることについて言及していると思います。

Mod_rewriteで使用できる変数の包括的なリストについては、 AskApacheのmod_rewriteデバッグチュートリアル をお勧めします。

書き換えルールを作成するときに最も一般的な間違い/落とし穴は何ですか?

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

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

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

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

まず、照合する予定の環境変数の内容を確認します。PHPがインストールされている場合、これはアプリケーションに次のブロックを追加するのと同じくらい簡単です:

<?php
  var_dump($_SERVER);
?>

...次に、ルール(できれば開発サーバーでのテスト用)を記述し、Apache ErrorLog ファイル内の一致またはアクティビティの不整合を書き留めます。

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

注意する必要があるmod_rewriteルールのSEOまたはパフォーマンスへの影響はありますか?

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

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

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

mod_rewriteがジョブに適したツールのように見えるかもしれないが、そうではない一般的な状況はありますか?

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

いくつかの一般的な例は何ですか?

AskApacheのmod_rewrite Tricks and Tips は、定期的にポップアップするほぼすべての一般的なユースケースをカバーしていますが、特定のユーザーの「正しい」ソリューションは、ユーザーの設定の洗練度と既存のディレクティブ(そのため、mod_rewriteの質問が表示されるたびに、ユーザーがどのotherディレクティブを使用しているかを確認することをお勧めします)。

39
danlefree

多くの管理者/開発者と同様に、私は長年にわたって複雑な書き換えルールと戦い続けており、既存のApacheドキュメントに不満を抱いているため、mod_rewriteが実際に機能し、対話する方法の底を掘り下げることを個人的なプロジェクトとして決定しましたApacheコアの残りの部分なので、過去数か月間、strace +でテストケースをインストルメント化し、ソースコードをドリルダウンして、これらすべてを処理してきました。

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

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

このため、リライトユーザーコミュニティを2つのカテゴリに分割し、それらを完全に別個のものとして扱う必要があると言っても過言ではありません。

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

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

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

3番目のコミュニティが存在する可能性があります。SHSプロバイダーの管理スタッフとサポートスタッフは、最終的に両方のキャンプに足を踏み入れ、上記の結果に苦しむ必要があります。

記事スタイルのブログ投稿をいくつか書きました(例: 。htaccessファイルの書き換えルールの使用の詳細 )。これは、この投稿を短くするためにここでは繰り返さない多くの詳細な点をカバーしています。私はいくつかの専用&VM FLOSSプロジェクトをサポートするだけでなく、独自の共有サービスも持っています。SHSのテスト手段として標準のLAMP VMを使用して始めましたアカウントですが、最終的には適切なミラーを作成する方がよいことがわかりましたVM(記述 こちら )。

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

  • PerDir処理で書き換えシステムが実際にどのように機能するかについての一貫した説明
  • .htaccess書き換えルールの記述方法に関する一連のガイドライン/ベストプラクティス
  • W3C htmlパーサーに似た単純なWebベースのリライトスクリプトパーサーですが、ユーザーはテストURIまたは同じのテストベクトルを入力して、リライトロジックフローの即時ログを取得できます。
  • ルールから組み込み診断を取得する方法のヒント(例:.

    • [E=VAR:EXPR]を使用して、EXPRが後方参照($ Nまたは%N)を展開し、ターゲットスクリプトの診断として使用できるようにするという事実を利用します。
    • [OR]、[C]、[SKIP]、および[L]フラグを使用して書き換えルールを局所的に並べ替え、書き換えスキーム全体が機能するようにする内部リダイレクトを利用する必要がない次に、ルール1として次のコードを追加して、すべてのループの面倒を回避できます。

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

rewritemapを使用する

Rewritemapsでできることはたくさんあります。 Rewritemapsは、Rewritemapディレクティブを使用して宣言され、RewritCond評価とRewriteRule Subsitutionsの両方で使用できます。

RewriteMapの一般的な構文は次のとおりです。

RewriteMap MapName MapType:MapSource

例えば:

RewriteMap examplemap txt:/path/to/file/map.txt

その後、次のような構成にマップ名を使用できます。

${examplemap:key}

マップにはキーと値のペアが含まれています。キーが見つかると、値が置き換えられます。単純なマップは単なるテキストファイルですが、ハッシュマップやSQLクエリを使用することもできます。詳細はドキュメントにあります:

http://httpd.Apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap

文字列をエスケープ解除します。

いくつかの操作に使用できる4つの内部マップがあります。特にエスケープしない文字列は便利です。

たとえば、クエリ文字列で文字列「café」をテストしたいとします。ただし、ブラウザはこれをエスケープしてからサーバーに送信するため、一致させたいすべての文字列のURLエスケープバージョンを特定する必要があります。または、エスケープ解除することもできます...

RewriteMap unescape int:unescape

RewriteCond %{QUERY_STRING}  (location|place)=(.*)
RewriteCond ${unescape:%2}   café
RewriteRule ^/find/$         /find/1234? [L,R]

1つのRewriteCondを使用してクエリ文字列パラメーターの引数をキャプチャする方法に注意してください。次に、2番目のrewriteCondのマップを使用して、エスケープを解除します。次に、これが比較されます。 %1には「場所」または「場所」のいずれかが含まれるため、リライトマップのキーとして%2を使用する方法にも注意してください。括弧を使用してパターンもグループ化すると、それらもキャプチャされますが、キャプチャの結果を使用するかどうかは関係ありません...

15

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

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

12
beldaz