リファレンス:mod_rewrite、URLの書き換え、および「かわいらしいリンク」の説明


142

「かわいらしいリンク」は頻繁に要求されるトピックですが、完全に説明されることはほとんどありません。mod_rewriteは「かわいらしいリンク」を作成する1つの方法ですが、複雑で、構文は非常に簡潔であり、理解するのが難しく、ドキュメントはHTTPのある程度の熟練度を前提としています。「きれいなリンク」がどのように機能し、mod_rewriteを使用してリンクを作成できるかを誰かが簡単に説明できますか?

その他の一般的な名前、エイリアス、クリーンURLの用語:RESTful URL、ユーザーフレンドリーなURL、SEOフレンドリーなURL、slugging、MVC URL(おそらく誤った名称)


2
SlugまたはSluggingは、かなりのURLの一般的なエイリアス/用語です。
Mike B

2
@Mike並べ替えますが、スラッグはかなりのURLの一部です。たとえば、記事の見出しがURLフレンドリーなフォームに変換され、その記事の識別子として機能する場合、スラッグはかなり具体的です。だからreference-mod-rewrite-url-rewriting-explainedスラッグ/questions/20563772/reference-mod-rewrite-url-rewriting-explainedは、かなりのURLです。
だます

2
.htaccessmod-rewriteタグは定期的に尋ねられることの多くをカバーしているので、この質問へのリンクを含めるように更新する必要があると思います。考え?
MikeRockétt2016

回答:


110

mod_rewriteの内容を理解するには、まずWebサーバーの動作を理解する必要があります。WebサーバーはHTTPリクエストに応答します。最も基本的なレベルのHTTPリクエストは次のようになります。

GET /foo/bar.html HTTP/1.1

これは、ブラウザからURL /foo/bar.htmlを要求するWebサーバーへの単純な要求です。ファイルを要求するのではなく、任意のURLを要求するだけであることを強調することが重要です。リクエストは次のようになります。

GET /foo/bar?baz=42 HTTP/1.1

これはURLのリクエストと同様に有効であり、ファイルとは明らかに関係ありません。

Webサーバーは、ポートをリッスンするアプリケーションであり、そのポートで着信するHTTPリクエストを受け入れ、応答を返します。Webサーバーは、要求に適切に対応する方法で、または応答するように構成した方法で、完全に自由に応答できます。この応答はファイルではなく、HTTP応答であり、任意のディスク上の物理ファイルとは関係ない場合があります。WebサーバーはApacheである必要はありません。永続的に実行され、HTTP要求に応答するポートに接続されている単なるプログラムである他の多くのWebサーバーがあります。自分で書くことができます。この段落は、URLがファイルと直接等しいという概念から離れることを目的としており、理解することが非常に重要です。:)

ほとんどのWebサーバーのデフォルト構成では、ハードディスク上のURLと一致するファイルを探します。たとえば、サーバーのドキュメントルートがに設定されて/var/wwwいる場合、ファイル/var/www/foo/bar.htmlが存在するかどうかを調べ、存在する場合はそれを提供します。「.phpの」内のファイルが終了した場合には、PHPインタプリタを起動します、その後、結果を返します。この関連付けはすべて完全に構成可能です。WebサーバーがPHPインタープリターを介してファイルを実行するために、ファイルの末尾が「.php」である必要はありません。URLは、何かが発生するためにディスク上の特定のファイルと一致する必要はありません。

mod_rewriteは、内部リクエスト処理を書き換える方法です。WebサーバーがURLのリクエストを受信した場合、Webサーバーが一致するディスク上のファイルを検索する前に、そのURLを別のURLに書き換えること/foo/barができます。簡単な例:

RewriteEngine On
RewriteRule   /foo/bar /foo/baz

このルールは、リクエストが「/ foo / bar」に一致するたびに、それを「/ foo / baz」に書き換えます。リクエストは、/foo/baz代わりにリクエストされたかのように処理されます。これは、たとえば次のようなさまざまな効果に使用できます。

RewriteRule (.*) $1.html

このルールは、あらゆるものに一致し()、それ.*キャプチャーし((..))、 "。html"を追加するように書き換えます。つまり、/foo/barリクエストされたURLであった場合、リクエストされた場合と同様に処理/foo/bar.htmlされます。正規表現のマッチング、キャプチャ、および置換の詳細については、http://regular-expressions.infoを参照してください。

別のよくあるルールはこれです:

RewriteRule (.*) index.php?url=$1

これも、すべてに一致し、最初に要求されたURLがurlクエリパラメータに追加されたファイルindex.phpに書き換えます。つまり、入ってくるすべてのリクエストに対して、ファイルindex.phpが実行され、このファイルはの元のリクエストにアクセス$_GET['url']できるので、必要なことを何でも実行できます。

主に、これらの書き換えルールをWebサーバー構成ファイルに入れます。Apacheを使用すると.htaccess、ドキュメントルート内(つまり、.phpファイルの横)で呼び出されるファイルにそれらを配置することもできます* 。

* プライマリApache構成ファイルで許可されている場合。これはオプションですが、多くの場合有効になっています。

mod_rewriteが行わないこと

mod_rewriteは、すべてのURLを魔法のように「きれい」にするわけではありません。これはよくある誤解です。Webサイトにこのリンクがある場合:

<a href="https://stackoverflow.com/my/ugly/link.php?is=not&amp;very=pretty">

mod_rewriteがそれをきれいにするためにできることは何もありません。これをきれいなリンクにするには、次のことを行う必要があります。

  1. リンクをきれいなリンクに変更します。

    <a href="https://stackoverflow.com/my/pretty/link">
    
  2. サーバーでmod_rewriteを使用して、/my/pretty/link上記のいずれかの方法でURLへのリクエストを処理します。

mod_substitute一緒にを使用して、発信HTMLページとそこに含まれるリンクを変換できます。ただし、これは通常、HTMLリソースを更新するだけではありません。)

mod_rewriteでできることはたくさんあり、非常に複雑なマッチングルールを作成できます。これには、いくつかの書き換えのチェーン、完全に異なるサービスまたはマシンへのリクエストのプロキシ、特定のHTTPステータスコードをレスポンスとして返す、リクエストのリダイレクトなどが含まれます。非常に強力で、基本的なHTTP要求/応答メカニズムを理解している場合は非常に便利です。リンクが自動的にきれいになるわけではありませ

可能なすべてのフラグとオプションについては、公式ドキュメントを参照してください。


6
ディスパッチャーへの優先なリライト方法として、バージョン2.2.16で導入されたFallbackResourceディレクティブに言及するかもしれません。
Darsstar 2013

78

decezeの答えを拡張するために、いくつかの他のmod_rewrite機能の例と説明を提供したいと思いました。

以下の例はすべて、すでにファイルに含まRewriteEngine Onれていることを前提としてい.htaccessます。

書き換え例

この例を見てみましょう:

RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=$1&title=$2 [NC,L,QSA]

ルールは4つのセクションに分かれています。

  1. RewriteRule -書き換えルールを開始します
  2. ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ -これはパターンと呼ばれますが、ここではルールの左側と呼びます-書き換えたいもの
  3. blog/index.php?id=$1&title=$2 -置換、または書き換えルールの右側と呼ばれる-書き換え先
  4. [NC,L,QSA] 後で詳しく説明する、コンマで区切られた書き換えルールのフラグです。

上記の書き換えにより、次のようなものにリンクでき、/blog/1/foo/実際にロードされます/blog/index.php?id=1&title=foo

ルールの左側

  • ^ページ名の始まりを示します-書き換えられますexample.com/blog/...example.com/foo/blog/...
  • (…)括弧の各セットは、ルールの右側で変数としてキャプチャできる正規表現を表します。この例では:
    • 大括弧の最初のセット-- ([0-9]+)は、長さが1文字以上で数値のみ(つまり0から9)のストリングと一致します。これ$1は、ルールの右側で参照できます
    • 括弧の第2のセットは、英数字(AZ、AZ、または0-9)を含む、長さが1つの文字の最小の文字列と一致するか、-または+(ノートが+このように実行することをエスケープすることなくとしてバックスラッシュでエスケープされた正規表現繰り返し文字)。これ$2は、ルールの右側で参照できます
  • ?直前の文字が、この場合には、オプションである手段は、両方の/blog/1/foo//blog/1/foo同じ場所に書き換えます
  • $ これが一致させたい文字列の終わりであることを示します

これらは、特定の条件を指定するために、書き換えルールの最後に角かっこで追加されるオプションです。繰り返しになりますが、ドキュメントで確認できるさまざまなフラグがたくさんありますが、より一般的なフラグのいくつかについて説明します。

NC

no caseフラグは、書き換えルールが大文字と小文字を区別しないことを意味します。したがって、上記の例のルールの場合、これは両方/blog/1/foo//BLOG/1/foo/(またはこれの任意のバリエーション)が一致することを意味します。

L

最後のフラグは、これが処理する必要がある最後のルールであることを示します。これは、このルールが一致する場合にのみ、現在の書き換え処理の実行でそれ以上のルールが評価されないことを意味します。ルールが一致しない場合、他のすべてのルールが通常どおり順番に試行されます。Lフラグを設定しない場合、以降のすべてのルールが、書き換えられた URLに後で適用さます。

END

Apache 2.4以降では、[END]フラグを使用することもできます。それと一致するルールは、以降のエイリアス/書き換え処理を完全に終了します。([L]たとえば、フラグは、たとえばサブディレクトリに書き戻すときなどに、2回目のラウンドをトリガーすることがよくあります。)

QSA

クエリ文字列の追加フラグにより​​、指定したURLに追加の変数を渡して、元の取得パラメーターに追加することができます。以下のようなものがあること当社たとえば、この手段/blog/1/foo/?comments=15ロードし/blog/index.php?id=1&title=foo&comments=15

R

このフラグは上の例で使用したものではありませんが、言及する価値があると思いました。これにより、ステータスコード(などR=301)を含めるオプションを使用して、httpリダイレクトを指定できます。たとえば、/ myblog /を/ blog /に301リダイレクトする場合は、次のようなルールを記述します。

RewriteRule ^/myblog/(*.)$ /blog/$1 [R=301,QSA,L]

書き換え条件

書き換え条件により、書き換えがさらに強力になり、特定の状況で書き換えを指定できるようになります。ドキュメントで読むことができる条件はたくさんありますが、いくつかの一般的な例に触れて説明します。

# if the host doesn't start with www. then add it and redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

これは非常に一般的な方法であり、ドメインの先頭にwww.(まだ存在しない場合)、301リダイレクトが実行されます。たとえば、http://example.com/blog/それをロードすると、http://www.example.com/blog/

# if it cant find the image, try find the image on another domain
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ http://www.example.com/$1 [L]

これはあまり一般的ではありませんが、ファイル名がサーバー上に存在するディレクトリまたはファイルである場合に実行されないルールの良い例です。

  • %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC] ファイル拡張子がjpg、jpeg、gif、またはpng(大文字と小文字を区別しない)のファイルに対してのみ書き換えを実行します。
  • %{REQUEST_FILENAME} !-f ファイルが現在のサーバーに存在するかどうかを確認し、存在しない場合にのみ書き換えを実行します
  • %{REQUEST_FILENAME} !-d ファイルが現在のサーバーに存在するかどうかを確認し、存在しない場合にのみ書き換えを実行します
  • 書き換えは別のドメインに同じファイルをロードしようとします

39

参考文献

Stack Overflowには他にも多くの優れたリソースがあります。

そして、初心者に優しい正規表現の概要:

よく使用されるプレースホルダー

  • .*空の文字列も含めて、すべてに一致します。このパターンをどこでも使用する必要はありませんが、多くの場合、最後のフォールバックルールで使用します。
  • [^/]+パスセグメントによく使用されます。スラッシュ以外のすべてと一致します。
  • \d+ 数値文字列のみに一致します。
  • \w+英数字と一致します。基本的にはの省略形です[A-Za-z0-9_]
  • [\w\-]+「スラッグ」スタイルのパスセグメントの場合、文字、数字、ダッシュ- _
  • [\w\-.,]+ピリオドとコンマを追加します。charclassesではエスケープされた\-ダッシュを[…]優先します。
  • \.文字通りのピリオドを示します。それ以外の場合は、.外側に[…]任意のシンボルのプレースホルダーがあります。

これらの各プレースホルダーは通常(…)、キャプチャグループとして括弧で囲まれます。そして、全体のパターンはしばしば^………$開始+終了マーカーにあります。「パターン」の引用はオプションです。

RewriteRules

次の例は、PHP中心であり、少しだけインクリメンタルであり、同様のケースに適応しやすくなっています。これらは単なる要約であり、多くの場合、より多くのバリエーションや詳細なQ&Aにリンクしています。

  • 静的マッピング
    /contact/about

    いくつかのページ名を内部ファイルスキームに短縮するのが最も簡単です。

     RewriteRule ^contact$  templ/contact.html
     RewriteRule ^about$    about.php
    
  • 数値識別子
    /object/123

    http://example.com/article/531既存のPHPスクリプトのようなショートカットを導入することも簡単です。数値プレースホルダーは、$_GETパラメーターに再マッピングするだけです。

     RewriteRule ^article/(\d+)$    article-show.php?id=$1
     #                      └───────────────────────────┘
    
  • スラグスタイルのプレースホルダー
    /article/with-some-title-slug

    このルールを簡単に拡張して、/article/title-stringプレースホルダーを許可できます。

     RewriteRule ^article/([\w-]+)$    article-show.php?title=$1
     #                       └────────────────────────────────┘
    

    スクリプト 、これらのタイトルをデータベースIDにマップできるようにする(または適合させる)必要があることに注意してください。RewriteRulesだけでは、薄い空気から情報を作成したり推測したりすることはできません。

  • プレフィックスが数値のスラグ
    /readable/123-plus-title

    したがって/article/529-title-slug、実際に使用される混合パスがよく見られます。

     RewriteRule ^article/(\d+)-([\w-]+)$    article.php?id=$1&title=$2
     #                      └───────────────────────────────┘
    

    これでtitle=$2、スクリプトは通常、とにかくデータベースIDに依存するため、とにかくパスをスキップすることができます。-title-slug任意のURLの装飾となっています。

  • 代替リストとの均一性
    /foo/… /bar/… /baz/…

    複数の仮想ページパスに同様のルールがある場合は、|代替リストを使用してそれらを照合および圧縮できます。そして再び、それらを内部のGETパラメータに再割り当てします。

     #                               ┌─────────────────────────┐
     RewriteRule ^(blog|post|user)/(\w+)$  disp.php?type=$1&id=$2
     #               └───────────────────────────────────┘
    

    RewriteRule複雑すぎる場合は、個別のに分割できます。

  • 関連するURLを異なるバックエンドにディスパッチする
    /date/SWITCH/backend

    代替リストのより実用的な使用法は、リクエストパスを個別のスクリプトにマッピングすることです。たとえば、日付に基づいて古いWebアプリケーションと新しいWebアプリケーションのURLを統一するには、次のようにします。

     #                   ┌─────────────────────────────┐
     #                   │                 ┌───────────┼───────────────┐
     RewriteRule ^blog/(2009|2010|2011)/([\d-]+)/?$ old/blog.php?date=$2
     RewriteRule ^blog/(\d+)/([\d-]+)/?$  modern/blog/index.php?start=$2
     #                          └──────────────────────────────────────┘
    

    これは単に2009-2011の投稿を1つのスクリプトに再マップし、その他すべての年は暗黙的に別のハンドラーに再マップします。より具体的なルールが最初に来ることに注意してください。スクリプトごとに異なるGETパラメータを使用する場合があります。

  • /パススラッシュ以外の区切り文字
    /user-123-name

    最も一般的には、仮想ディレクトリ構造をシミュレートするRewriteRulesが表示されます。しかし、あなたは創造的である必要はありません。-ハイフンをセグメント化または構造化に使用することもできます。

     RewriteRule ^user-(\d+)$    show.php?what=user&id=$1
     #                   └──────────────────────────────┘
     # This could use `(\w+)` alternatively for user names instead of ids.
    

    一般的な/wiki:section:Page_Nameスキームの場合:

     RewriteRule ^wiki:(\w+):(\w+)$  wiki.php?sect=$1&page=$2 
     #                   └─────┼────────────────────┘       │
     #                         └────────────────────────────┘
    

    ときどき、/-delimiters を交互に使用し:たり.、同じルールで使用したりすることもできます。または、2つのRewriteRulesを再度使用して、バリアントを異なるスクリプトにマップします。

  • オプションの末尾の/スラッシュ
    /dir=/dir/

    ディレクトリ形式のパスを選択すると、ファイナルの有無にかかわらず到達可能にすることができます /

     RewriteRule ^blog/([\w-]+)/?$  blog/show.php?id=$1
     #                         ┗┛
    

    これでhttp://example.com/blog/123との両方が処理され/blog/123/ます。また、この/?$アプローチは他のRewriteRuleに簡単に追加できます。

  • 仮想パスの柔軟なセグメント
    .*/.*/.*/.*

    遭遇するほとんどのルールは、制約された/…/リソースパスセグメントのセットを個々のGETパラメータにマッピングします。ただし一部のスクリプトは、可変数のオプションを処理します。Apache regexpエンジンでは、それらの任意の数をオプションにすることはできません。ただし、自分で簡単にルールブロックに拡張できます。

     Rewriterule ^(\w+)/?$                in.php?a=$1
     Rewriterule ^(\w+)/(\w+)/?$          in.php?a=$1&b=$2
     Rewriterule ^(\w+)/(\w+)/(\w+)/?$    in.php?a=$1&b=$2&c=$3
     #              └─────┴─────┴───────────────────┴────┴────┘
    

    最大5つのパスセグメントが必要な場合は、このスキームを5つのルールにコピーします。もちろん、[^/]+それぞれより具体的なプレースホルダーを使用できます。ここでは、どちらも重複していないため、順序はそれほど重要ではありません。したがって、最も頻繁に使用されるパスを最初に持つことは問題ありません。

    別の?p[]=$1&p[]=$2&p[]=3方法として、ここでクエリ文字列を介してPHPの配列パラメーターを利用することもできます。(キャッチオールルールを使用し、スクリプト自体がREQUEST_URIからセグメントを拡張することが一般的ですが)。

    参照:URLパスセグメントをクエリ文字列のキーと値のペアに変換するにはどうすればよいですか?

  • オプションのセグメント
    prefix/opt?/.*

    一般的なバリエーションは、オプションのプレフィックスルール内に含めることです。これは通常、静的な文字列または制約されたプレースホルダーがある場合に意味があります。

      RewriteRule ^(\w+)(?:/([^/]+))?/(\w+)$  ?main=$1&opt=$2&suffix=$3
    

    ここで、より複雑なパターンは(?:/([^/])+)?、単に非キャプチャ (?:…)グループをラップし、それをオプションにします)?。含まれるプレースホルダー([^/]+)は置換パターン$2になりますが、中間/…/パスがない場合は空になります。

  • 残りをキャプチャ
    /prefix/123-capture/…/*/…whatever…

    前に述べたように、あまりにも一般的な書き換えパターンを必要とすることはあまりありません。ただし、静的な比較と特定の比較を.*時々組み合わせることは意味があります。

     RewriteRule ^(specific)/prefix/(\d+)(/.*)?$  speci.php?id=$2&otherparams=$2
    

    これにより、任意の/…/…/…後続パスセグメントがオプション化されました。もちろん、それらを分割するための処理スクリプトが必要であり、抽出されたパラメーター自体をvariabl-ifyします(これはWeb- "MVC"フレームワークが行うことです)。

  • 末尾のファイル「拡張子」
    /old/path.HTML

    URLにはファイル拡張子がありません。これは、この参照全体に関するものです(= URLは仮想ロケーターであり、必ずしも直接のファイルシステムイメージではありません)。ただし、以前に1:1のファイルマッピングがあった場合は、より簡単なルールを作成できます。

     RewriteRule  ^styles/([\w\.\-]+)\.css$  sass-cache.php?old_fn_base=$1
     RewriteRule  ^images/([\w\.\-]+)\.gif$  png-converter.php?load_from=$2
    

    他の一般的な使用法は.html、新しい.phpハンドラーへの古いパスの再マッピング、または個々の(実際の/実際の)ファイルに対してのみディレクトリ名にエイリアスを付けることです。

  • ピンポン(リダイレクトと一括書き換え)
    /ugly.html←→/pretty

    したがって、decezeで概説されているように、ある時点でHTMLページを書き直して、きれいなリンクのみを運ぶようにします。その間、まだブックマークから、古いパスのリクエストを受け取る場合があります。回避策として、ブラウザにピンポンして、新しいURLを表示/確立できます。

    この一般的なトリックには、着信URLが廃止された/醜い命名スキームに従うたびに30x / Location リダイレクトを送信することが含まれます。その後、ブラウザーは新しい/かなりのURLを再要求します。このURLは、後で(内部的に)元の場所または新しい場所に書き換えられます。

     # redirect browser for old/ugly incoming paths
     RewriteRule ^old/teams\.html$ /teams [R=301,QSA,END]
    
     # internally remap already-pretty incoming request
     RewriteRule ^teams$ teams.php        [QSA,END]
    

    この例では、安全に代替するのでは[END]なく、代わりに使用していることに注意してください[L]。古いApache 2.2バージョンの場合は、クエリ文字列パラメータの再マッピングに加えて、他の回避策を使用できます。たとえば 、醜いURLにリダイレクトし、無限ループなしで醜いパスに再マップします。

  • パターン内のスペース
    /this+that+

    ブラウザのアドレスバーではそれほどきれいではありません、URLでスペースを使用できます。書き換えパターンには、バックスラッシュでエスケープした\␣スペースを使用します。そうでなければ"全体のパターンや置換を-quote:

     RewriteRule  "^this [\w ]+/(.*)$"  "index.php?id=$1"  [L]
    

    クライアントは+またはを使用してURLをシリアル化します%20、スペーススペース用の。しかし、RewriteRulesでは、すべての相対パスセグメントのリテラル文字で解釈されます。

頻繁な重複:

流行している.htaccess落とし穴

これを塩の粒と一緒に服用してください。すべてのアドバイスをすべてのコンテキストに一般化できるわけではありません。これは、よく知られているいくつかの自明ではない障害の簡単な要約です。

  • 有効にしmod_rewrite.htaccess

    ディレクトリごとの構成ファイルでRewriteRulesを実際に使用するには、次のことを行う必要があります。

    • サーバーがAllowOverride All有効になっていることを確認します。そうし.htaccessないと、ディレクトリごとのディレクティブが無視され、RewriteRulesが機能しません。

    • 明らかにしているmod_rewrite有効にお使いにhttpd.confモジュールセクション。

    • ルールの各リストの前にRewriteEngine Onスティルを付けます。<VirtualHost>および<Directory>セクションでmod_rewriteは暗黙的にアクティブですが、ディレクトリごとの.htaccessファイルは個別に呼び出す必要があります。

  • 先頭のスラッシュ^/が一致しません

    通常、.htaccessRewriteRuleパターンを開始しないでください^/

     RewriteRule ^/article/\d+$  …
                  ↑
    

    これは古いチュートリアルでよく見られます。かつては、Apache 1.xの古いバージョンでは正しいものでした。現在、RewriteRulesでは、リクエストパスは便利な完全ディレクトリ相対パス.htaccessです。リード/アウトはそのままにしておきます。

    ・ただし、<VirtualHost>セクションの先頭のスラッシュは引き続き正しいことに注意してください。これが^/?、ルールの平準化のためにオプション化されていることが多い理由です。
    ・または、RewriteCond %{REQUEST_URI}あなたがまだリーディングのためにマッチすることを使用するとき/
    ・も参照 Webmaster.SE:mod_rewriteパターンで先頭のスラッシュ(/)が必要になるのはいつですか?

  • <IfModule *> ラッパーがなくなりました!

    あなたはおそらくこれを多くの例で見ました:

    <IfModule mod_rewrite.c>
       Rewrite… 
    </IfModule>
    
    • それ意味があります<VirtualHost>セクションでます-ScriptAliasMatchなどの別のフォールバックオプションと組み合わせた場合。(しかし、誰もそれをしません)。
    • そして、それは一般的にデフォルトで配布されています .htaccess、多くのオープンソースプロジェクトルールセット。そこでは単にフォールバックとして意図されており、「醜い」URLをデフォルトとして機能させ続けます。

    ただし、通常は自分のファイルではそれを望まないでしょ.htaccess

    • まず、mod_rewriteはランダムに解除されません。(もしそうなら、あなたはより大きな問題を抱えているでしょう)。
    • それが本当に無効になっていても、RewriteRulesはまだ機能しません。
    • HTTP 500エラーを防ぐためのものです。それが通常達成することは、404代わりにユーザーにHTTP エラーを与えることです。(考えれば、それほどユーザーフレンドリーではありません。)
    • 実際には、より有用なログエントリまたはサーバー通知メールを抑制します。RewriteRulesが機能しない理由について、あなたは賢明ではありません

    一般化されたセーフガードとして魅力的であるように見えるものは、実際には障害になることがよくあります。

  • RewriteBase必要がない限り使用しないでください

    多くのコピーと貼り付けの例には、 RewriteBase /ディレクティブます。とにかく、これは暗黙のデフォルトです。したがって、実際にはこれは必要ありません。これは、派手なVirtualHostリライティングスキームの回避策であり、一部の共有ホスティング事業者のDOCUMENT_ROOTパスを誤解しています。

    より深いサブディレクトリにある個々のWebアプリケーションで使用することは理にかなっています。このような場合、RewriteRuleパターンを短縮できます。一般に、ディレクトリごとのルールセットでは相対パス指定子を使用することをお勧めします。

    RewriteBaseが.htaccessでどのように機能するかも参照してください。

  • 無効にする MultiViews仮想パスが重複する場合はにする

    URL書き換えは、主に仮想着信パスをサポートするために使用されます。一般的に、あなただけの1ディスパッチャスクリプト(持っているindex.php)、またはいくつかの個々のハンドラを(articles.phpblog.phpwiki.php、...)。後者は衝突するかもしれません、同様の仮想RewriteRuleパスと競合するます。

    /article/123たとえば、リクエストarticle.php/123PATH_INFOで暗黙的にマッピングできます。次に、平凡なRewriteCond !-f+を使用してルールを保護するか!-d、PATH_INFOサポートを無効にするか、単に無効にする必要がありOptions -MultiViewsます。

    常にそうしなければならないということではありません。コンテンツネゴシエーションは、仮想リソースの単なる自動化です。

  • 順序は重要です

    mod_rewriteについて まだ知りたくない場合は、すべてを参照してください。複数のRewriteRulesを組み合わせると、多くの場合、相互作用が発生します。これは[L]、フラグごとに習慣的に防止するものではありませんが、一度精通すれば採用するスキームです。あなたがすることができ、再再再の書き込み、それが実際のターゲットハンドラに到達するまで、別のルールから仮想パスを。

    それでも、多くの場合初期のルールに最も具体的なルール(固定された文字列/forum/…パターン、またはより制限的なプレースホルダー[^/.]+)を含める必要があります。一般的なスラップオールルール()は、後のルールに任せるのが適切です。(例外は、1次ブロックとしてのガードです。).*RewriteCond -f/-d

  • スタイルシートと画像が機能しなくなる

    仮想ディレクトリ構造を導入すると/blog/article/123、HTMLなどの相対リソース参照(など<img src=mouse.png>)に影響します。これは次の方法で解決できます。

    • サーバー絶対参照のみを使用するhref="https://stackoverflow.com/old.html"か、src="/logo.png"
    • 多くの場合、単に<base href="https://stackoverflow.com/index">HTML <head>セクションに追加するだけです。これにより、相対的な参照が以前のものに暗黙的に再バインドされます。

    別の方法として、元の場所に再バインド.cssまたは.pngパスするためのRewriteRulesをさらに作成することもできます。しかし、それはどちらも不要であるか、余分なリダイレクトが発生し、キャッシングが妨げられます。

    参照:CSS、JS、画像がきれいなURLで表示されない

  • RewriteCondsは1つのRewriteRuleをマスクするだけです

    一般的な誤解は、RewriteCondが複数のRewriteRulesをブロックすることです(それらは視覚的にまとめられているため)。

     RewriteCond %{SERVER_NAME} localhost
     RewriteRule ^secret  admin/tools.php
     RewriteRule ^hidden  sqladmin.cgi
    

    デフォルトではありません。フラグを使用してそれらチェーンでき[S=2]ます。そうでなければ、それらを繰り返す必要があります。場合によっては、「逆」のプライマリルールを作成して、書き換え処理を早く[終了]することもできます。

  • QUERY_STRINGはRewriteRulesから除外されます

    RewriteRule index.php\?x=ymod_rewriteはデフォルトで相対パスと比較するだけなので、と一致させることはできません。ただし、次の方法で個別に一致させることができます。

     RewriteCond %{QUERY_STRING} \b(?:param)=([^&]+)(?:&|$)
     RewriteRule ^add/(.+)$  add/%1/$1  # ←──﹪₁──┘
    

    クエリ文字列変数をmod_rewriteと一致させるにどうすればよいですか?もご覧ください

  • .htaccess<VirtualHost>

    ディレクトリごとの構成ファイルでRewriteRulesを使用している場合、正規表現のパフォーマンスについて心配することは無意味です。Apacheは、共通のルーティングフレームワークを使用して、PHPプロセスよりも長いコンパイル済みPCREパターンを保持します。ただし、トラフィック量の多いサイトの場合は、戦いのテストが終わったら、ルールセットをvhostサーバー構成に移動することを検討してください。

    この場合、オプションの^/?ディレクトリセパレータプレフィックスを優先します。これにより、PerDirとサーバー構成ファイルの間でRewriteRulesを自由に移動できます。

  • 何かがうまくいかないときはいつでも

    フレットではありません。

    • 比較access.logしてerror.log

      多くの場合、RewriteRuleがどのように動作しないかは、自分のerror.logandを見ただけでわかりますaccess.log。アクセス時間を相互に関連付けて、最初に着信したリクエストパスと、Apacheが解決できなかったパス/ファイルを確認します(エラー404/500)。

      これは、どのRewriteRuleが原因かはわかりません。しかし、のようなアクセスできない最終的なパス/docroot/21-.itle?index.phpは、どこをさらに検査するかを与える可能性があります。それ以外の場合は、予測可能なパスが得られるまでルールを無効にします。

    • RewriteLogを有効にする

      Apache RewriteLogのドキュメントを参照してください。デバッグの場合は、vhostセクションで有効にできます。

      # Apache 2.2
      RewriteLogLevel 5
      RewriteLog /tmp/rewrite.log
      
      # Apache 2.4
      LogLevel alert rewrite:trace5
      #ErrorLog /tmp/rewrite.log
      

      これにより、受信したリクエストパスが各ルールによってどのように変更されるかの詳細な概要が得られます。

      [..] applying pattern '^test_.*$' to uri 'index.php'
      [..] strip per-dir prefix: /srv/www/vhosts/hc-profi/index.php -> index.php
      [..] applying pattern '^index\.php$' to uri 'index.php'
      

      これは、過度に一般的なルールと正規表現の事故を絞り込むのに役立ちます。

      参照:
      .htaccessが機能しない(mod_rewrite)
      .htaccess書き換えルールをデバッグするためのヒント

    • 質問する前に

      ご存知かもしれませんが、Stack Overflowはmod_rewriteに関する質問に非常に適しています。それらを話題に 前の研究の試み(回避の冗長回答)を含むことにより、基本的な証明 理解、そして:

      • 入力URL、改ざんされたターゲットパス、実際のディレクトリ構造の完全な例を含めます。
      • 完全なのRewriteRuleセットが、また、推定欠陥1アウトシングル。
      • ApacheとPHPのバージョン、OSタイプ、ファイルシステム、DOCUMENT_ROOT、および$_SERVERパラメーターの不一致に関するPHP 環境。
      • access.logおよびからの抜粋でerror.log、既存のルールが解決した内容を確認します。さらに良いことに、rewrite.log要約。

      これにより、より速く正確な答えが得られ、他の人にとってより役立つものになります。

  • コメントする .htaccess

    どこかから例をコピーする場合は、を含めるように注意してください# comment and origin link。アトリビューションを省略するのは単にマナーが悪いだけですが、後でメンテナンスをするのはしばしば大変です。コードまたはチュートリアルのソースを文書化します。特に、理解していない間は、魔法のブラックボックスのように扱ってはいけないことに、もっともっと関心を持つべきです。

  • 「SEO」ではない-URL

    免責事項:ただのペットのおしっこ。「SEO」リンクなどと呼ばれるかなりのURL書き換えスキームをよく耳にします。これはグーグルの例には役立ちますが、日付が誤っているためです。

    最近の検索エンジンは、パスセグメントやクエリストリングによって影響を受けることは.htmlありません。こうしたアルタビスタなどの古いの検索エンジンは、やりました.php?id=123潜在的ambigiousアクセスパスでウェブサイトをクロール回避します。最近のクローラーは、多くの場合、深いWebリソースを欲しがっています。

    「きれいな」URLを概念的に使用する必要があるのは、Webサイトをユーザーフレンドリーにすることです。

    1. 読みやすく、明確なリソーススキームを持っている。
    2. URLが長期間有効であることを確認します(別名パーマリンク)。
    3. を通じて発見可能性を提供します/common/tree/nesting

    ただし、準拠のための固有の要件を犠牲にしないでください。

ツール

ほとんどのGETパラメータURLのRewriteRulesを生成するさまざまなオンラインツールがあります。

ほとんどの場合[^/]+、一般的なプレースホルダーを出力するだけですが、ささいなサイトには十分です。


それでも少し書き直し、リンクの追加が必要で、多くのサブヘッドラインはやや不愉快です。ここでは他の回答といくつかの重複があるため、おそらく削減できます。それは主に視覚的な例と、一般的な問題のリストです。
マリオ2015

3
こんな答えの美しさを久しぶりに見た!読んでいる間、目が輝いています。そのような答えを投稿するのをやめないでください:)
Rizier123

1
素晴らしいポスト。mod_rewriteの基本概念をすぐに理解できました。
breez

6

mod_rewriteの代替

RewriteRulesを使用しなくても、多くの基本的な仮想URLスキームを実現できます。Apacheでは.php、拡張機能なしで、仮想PATH_INFO引数を使用してPHPスクリプトを呼び出すことができます。

  1. PATH_INFOを使用して、Luke

    今日でAcceptPathInfo Onは、多くの場合、デフォルトで有効になっています。基本的に.php、他のリソースURLが仮想引数を運ぶことを許可します。

    http://example.com/script.php/virtual/path
    

    これ/virtual/pathはPHPで表示され$_SERVER["PATH_INFO"]、追加の引数を好きなように処理できます。

    これは、便利にはApache別の入力経路セグメントを有するようではない$1$2$3および別個として渡す$_GETPHPに変数。構成作業を少なくして、「きれいなURL」をエミュレートするだけです。

  2. マルチビューを有効にして.php拡張機能を非表示にする

    .phpURLの「ファイル拡張子」も避けるための最も簡単なオプションは、以下を有効にすることです。

    Options +MultiViews
    

    これは、ベース名が一致するため、Apache article.phpでHTTPリクエストを選択します/article。そして、これは前述のPATH_INFO機能と一緒にうまく機能します。したがって、次のようなURLを使用できますhttp://example.com/article/virtual/title。これは、複数のPHP呼び出しポイント/スクリプトを持つ従来のWebアプリケーションがある場合に意味があります。

    ただし、MultiViewsには別の目的や幅広い目的があります。Apacheはベース名が一致する他のファイルを常に検索するため、パフォーマンスが非常に低下します。これは、実際のためのものだコンテンツネゴシエーションのブラウザは(のような利用可能な資源の中で最良の選択肢を受けるので、article.en.phparticle.fr.phparticle.jp.mp4)。

  3. 拡張なし.phpスクリプトのSetTypeまたはSetHandler

    .phpURLのサフィックスの持ち越しを回避するためのより直接的なアプローチは、他のファイルスキームのPHPハンドラー構成することです。最も簡単なオプションは、デフォルトのMIME /ハンドラタイプを.htaccess次のようにオーバーライドすることです。

    DefaultType application/x-httpd-php
    

    この方法では、article.phpスクリプトの名前を単にarticle(拡張子なしで)変更できますが、それでもPHPスクリプトとして処理させることができます。

    拡張子のないファイルはすべてPHPを介してパイプされるため、これはセキュリティとパフォーマンスに影響を与える可能性があります。したがって、この動作を個別のファイルのみに設定することもできます。

    <Files article>
      SetHandler application/x-httpd-php
      # or SetType 
    </Files>
    

    これは、サーバーの設定と使用されているPHP SAPIによって多少異なります。一般的な代替案には、ForceType application/x-httpd-phpまたはがありAddHandler php5-scriptます。

    このような設定は、1つ.htaccessからサブフォルダに伝達されることに注意してください。あなたは、常にスクリプトの実行(無効にする必要がありますSetHandler Noneし、Options -Execまたはphp_flag engine off静的リソース用など)、およびアップロード/ディレクトリなど

  4. その他のApache書き換えスキーム

    その多くのオプションの中で、Apacheはmod_alias機能を提供します-これは時々mod_rewrites RewriteRulesと同じように機能します。ただし、これらのほとんどは<VirtualHost>セクションで設定する必要がありますが、ディレクトリごとの.htaccess設定ファイルでは設定しないでください。

    • ScriptAliasMatch主にCGIスクリプト用ですが、PHPでも動作するはずです。これは、他と同じように正規表現を許可しますRewriteRule。実際、これはおそらく、すべてをカバーするフロントコントローラーを構成するための最も堅牢なオプションです。

    • そして、プレーンAliasはいくつかの単純な書き換えスキームにも役立ちます。

    • 単純なErrorDocumentディレクティブでさえ、PHPスクリプトに仮想パスを処理させることができます。ただし、これは扱いにくい回避策ですが、GETリクエスト以外は禁止され、定義によりerror.logがフラッディングされます。

    その他のヒントについては、http://httpd.apache.org/docs/2.2/urlmapping.htmlを参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.