.htaccessのRewriteについて語る

この記事はAIによって中国語から翻訳されました。

さて、この記事の読者層はかなり限られているようですが、もしこのタイトルが何を意味するか分からない場合は……読まなくても大丈夫です、ははは。

Apacheには重要な機能の一つとして、URLとファイルを完全に切り離すことができ、Rewriteルールを使って実際のURLを変更できるという点があります。
しかもこの機能は実は非常に便利で、最も一般的な用途は以下の通りです:

  • ドメイン変更やファイル移転時に、古いアドレスからも対応するファイルにアクセスできるようにする。
  • 直リンクを防止し、特定のサイトからのみファイル参照を許可する。
  • 擬似静的化により、.phpファイル名を隠して.html形式やパス形式にする。
  • 404などのエラーページをカスタマイズする。

最近、自分の2つのサイトをいじっていたので、直リンク防止機能以外はすべて実践してみました……
正直なところ、これは本当に人間に優しくない代物ですね。特に慣れていないときは、他人のコードをコピーしても理解できず、どう修正すればいいかも分かりません……
自分の要件を追加しようとするとさらに途方に暮れるので、結局半日かけて勉強しました……

では、これからこの仕組みについて簡単に紹介します……
まず.htaccessとは何かから説明しましょう:

.htaccessファイル(または「分散設定ファイル」)は、ディレクトリ単位で設定を変更する方法を提供します。つまり、特定のドキュメントディレクトリに1つ以上のディレクティブを含むファイルを配置することで、そのディレクトリおよびすべてのサブディレクトリに適用されます。ユーザーとして使用できるコマンドには制限があり、管理者はApacheのAllowOverrideディレクティブを通じて設定できます。

概説すると、htaccessファイルはApacheサーバー内の設定ファイルであり、関連ディレクトリ下のWebページ設定を担当します。htaccessファイルを使用することで、Webページの301リダイレクト、カスタム404エラーページ、ファイル拡張子の変更、特定のユーザーまたはディレクトリへのアクセス許可/拒否、ディレクトリリストの禁止、デフォルトドキュメントの設定などを実現できます。

.htaccessを有効にするには、httpd.confを修正してAllowOverrideを有効にし、AllowOverrideを使用して特定のコマンドの使用を制限できます。.htaccess以外のファイル名を使用する必要がある場合は、AccessFileNameディレクティブで変更できます。例えば、.configを使用する必要がある場合、サーバー設定ファイルで次のように設定できます:AccessFileName .config。

もちろん、実際にはこれらの設定はhttpd.confやvhosts内の仮想ホスト設定ファイルに直接記述することもできますが、
.htaccessの方が制御や修正が容易で、サービスを再起動する必要がないなどの利点があります。
その制御範囲はファイルが存在するフォルダとそのサブフォルダに限られるため、サブフォルダ内で使用することでより狭い範囲の制御が可能です。
欠点も明らかで、パフォーマンスへの影響です。AllowOverrideで.htaccessファイルが有効になっている場合、
Apacheはアクセスごとに現在のディレクトリおよびすべての親ディレクトリで.htaccessファイルを検索する必要があります。
.htaccessファイルが存在しない場合でも検索が行われるため、実際に使用されているかどうかに関わらず、.htaccessを有効にするとパフォーマンスが低下します。

もちろん、私のような小規模サイトではこうしたパフォーマンス要因を考慮する必要は全くないので、思い切って実践を始めました~~~~
通常このファイルはドメインのルートディレクトリにあり、存在しない場合は新規作成し、存在する場合は直接編集します。
ただし、編集前に既存の内容を理解しておくことをお勧めします……競合を防ぐためです。

まずは基本構文から説明しましょう:

<IfModule mod_rewrite.c>
	RewriteEngine On
	语句。。。。
</IfModule>

ここでRewriteEngine OnとOffを使うことで、以降のすべてのステートメントの有効・無効を簡単に制御できます。
デバッグ時にも役立ちますし、個別の行は先頭に#を追加することでコメントアウトできます。

さて、次によく使われるステートメントについて説明します:
通常、各リダイレクトは次のような構造になります:
まず1つ以上のRewriteCondを条件として設定し、条件を満たした場合に、
RewriteRuleによってリダイレクトを実行します。
よく使われる変数にはHTTP_HOST(ドメイン名)、REQUEST_URI(ドメイン名の後の部分)、REQUEST_FILENAME(ファイル名)があります。
最後にパラメータがあり、よく使われるものは以下の通りです:[NC]:大文字小文字を区別しない、[R]:リダイレクト、[L]:後続の処理を停止。
条件には正規表現が使用されるため、正規表現に慣れている人にとっては簡単ですが、
慣れていない人には全く理解できないでしょう。具体的な知識はこちらで補完できます:http://zh.wikipedia.org/zh/正则表达式
主に注意すべきなのは開始と終了のマークです。例えば空文字列の場合は^$となります。
その他の変数パラメータとその意味については、こちらを参照してください:http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html

以下にいくつか例を挙げて説明します。例えば、domain.comへのすべてのアクセスをwww.domain.comへリダイレクトする場合、
もちろん逆も可能ですし、ドメインの置換にも使用できます。
ここでの条件はHTTP_HOSTがdomain.comに一致すること、ルールはwww.domain.comへリダイレクトし、後続のコンテンツは保持されます。
大文字小文字を区別せず、永久リダイレクトを行います。

RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

同様に、前のブログ記事で触れたように、/wp-content/uploads/へのリクエストをcdn.cnsjw.cn/uploads/へリダイレクトする場合:

RewriteCond %{REQUEST_URI} ^/wp-content/uploads/ 
RewriteRule /wp-content/uploads/(.*) https://img.cnsjw.cn/$1 [R=301,L]

ここでリダイレクトとは、ブラウザや検索エンジンに対して、このアドレスが永続的に変更されたことを伝えることを意味し、
リダイレクト後は新しいアドレスへ直接ジャンプします。

他にもエラーページのカスタマイズがありますが、構文は非常にシンプルです:

ErrorDocument 404 /404.html

これで404エラーのカスタムページを実現できます。

Rewriteの最も一般的な用途はリダイレクトではなく、擬似静的化です。
例としてeitdesign.comを挙げますが、このサイトの以前のページロジックは
eitdesign.com/home、eitdesign.com/aboutなどで、当時は擬似静的ではなく真の静的ページでした……
実装方法はhome、aboutなどのフォルダを作成し、その中でindexファイルを直接使用して現在のページを出力するというものでした。

当時のサイト全体のファイル構造は以下の通りです:
QQ20140714-1

この方法には多くの問題がありました。例えば、各ページごとに記述が必要で、このようなシンプルな小規模サイトでしか実現できませんでした。
修正も面倒ですし、すべてのページファイル名がindexなので、多く開くと混乱します……
英語版もありましたが、新たに/enフォルダを作成してこれらのファイルをもう一度書く余裕はありませんでした……
そこで?lan=enを使って言語バージョンを制御しました。当時このパラメータがなければ中国語版、あれば英語版という扱いでした。
これによりファイル名が統一されず、明らかにユーザーフレンドリーではありませんでした。

現在採用している方法は、serviceページを除くすべてのページをindex.phpで処理し、
コンテンツ部分はxmlから読み込み、コードは機能部分のみを実装するというものです。現在のファイル構造は以下の通りです:
QQ20140714-2

そこで、すべてのservicesリクエストに対して別のrewriteを行い、残りの部分はすべてindex.php?p=へ直接rewriteするようにしました。
こうすることで、index.php内で渡されたpパラメータを判定するだけで済みます。例えばhttp://www.eitdesign.com/home/enにアクセスすると、
実際にはhttp://www.eitdesign.com/index.php?p=home/enにアクセスしていることになります。
そしてPHPでこのパラメータを処理するのはずっと簡単になり、explodeを使って/で分割し、/の前と後ろの部分を判定することで、
どのページにアクセスしようとしているか、どの言語バージョンかを簡単に知ることができます。

また、ファイル名やフォルダ名でないことを先に判定してからRewriteを行う必要があります……そうでないと通常のファイルにアクセスできなくなります。

RewriteCond %{REQUEST_URI} services/en/
RewriteRule . /services/en.html [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} services/
RewriteRule . /services/cn.html [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d	
RewriteRule ^(.*)$ index.php?p=$1

これで擬似静的化が実現できました……

もう一つの要件は、www.eitdesign.comへのアクセスをwww.eitdesign.com/home/へリダイレクトすることです。

RewriteRule ^$ /home/ [R=301,L]

ここで注意すべき点は、vhosts内で設定している場合、www.eitdesign.comにアクセスした際に、
REQUEST_URIは空ではなく/になるということです。空になるのは.htaccess内で設定した場合のみです。

まとめると、私もまだ初心者ですが、それでもいくつかのルールを書くことはできます……
主に注意すべき点は以下の通りです:

  • 判定時には条件の開始と終了マークを適切に設定しないと、包含関係になってしまいます。
  • 重複リダイレクトや無限ループなどの問題を避けること。
  • またステートメントの順序も重要で、ある条件を満たしたら末尾に以下を追加できます:[L]後続の処理を停止。
  • サブドメインに注意してください。あるディレクトリのサブディレクトリである場合、上位ディレクトリの.htaccessもサブドメインに適用されるため、エラーが発生する可能性があります。サブドメインディレクトリの.htaccessでリダイレクトを禁止することができます。

自分でサーバーを設定するのは実は結構楽しいものです。各種エラーログをこまめに確認することを忘れずに、
自分のコードやサーバー設定を継続的に改善していきましょう。

コメントはWeChat公式アカウントへ

, , ,


サポート