.htaccess の書き方

.htaccess とは

close[1] Apache HTTP Server
Webサーバソフトウェアが "Apache" である必要があります。

.htaccess とは、Webサーバの動作を制御するための設定ファイル [1] です。設定例としては、特定のファイルやディレクトリのアクセスを禁止したり、HTTP 404(Not Found:未検出)エラーページをカスタマイズすることもできます。.htaccess は設置しなくともWebサイトは問題なく動作しますが、セキュリティやパフォーマンスの観点から導入をおすすめします。

以降は、さくらインターネットのレンタルサーバで .htaccess を利用する場合について説明します。レンタルサーバによっては .htaccess の利用を禁止している場合や、設定できない項目もありますので、利用できるかは公式ヘルプページを参照するようにしましょう。また、詳細な情報については Apache の公式ドキュメントを参照して下さい。

.htaccess のルール

.htaccess の書き方にはルールがあり、ルールを違反すると "500 internal server error" が発生します。500 internal server error が発生すると、以下のような画面が表示されWebページが表示されなくなります。そのため .htaccess を設置する場合は十分な動作確認を行いましょう。

ファイル名

.htaccess のファイル名は、そのまま ".htaccess" になります。先頭に . がついていることに注意して下さい。先頭に . がつくファイルはUNIX系のOSで隠しファイルを意味しており、ファイル名がない拡張子だけのファイルという意味ではありません。

Windowsでは初期設定で拡張子の表示が省略されているため、ファイル名が気付かずに ".htaccess.txt" となっている場合があります。".htaccess.txt" では、サーバが正しく認識できないため、動作しません。また、拡張子が自動で付与されて ".htaccess" というファイル名が作成できない場合は、 ".htaccess.txt" のファイル名で一旦作成し、アップロード後にWebサーバ上で ".htaccess" にリネームします。

ただし .htaccess のファイル名は後述する httpd.conf の AccessFileName ディレクティブで定義できるため、必ずしも .htaccess ではない場合があります。もしも .htaccess が機能せず、500 internal server error も発生しない場合は .htaccess のファイル名を確認してみて下さい。以下は .htaccess のファイル名を .acl に変更している例です。

# 設定ファイル名を .htaccess ではなく .acl にしている例
AccessFileName .acl
httpd.conf に含まれている .htaccess の設定例

コメントアウト

.htaccess では、# から始まる行がコメントアウトされます。行の途中でもコメントをつけることが可能ですが、Apacheのバージョンや、記述場所によってはエラーになるため、基本的にコメント行は独立させましょう。それでも行の途中でコメントをつける場合は、" で囲むことでコメントアウトされます。ただし、Apache ver1.3系ではエラーになるため、Apache ver2.0系以降である必要があります。

# ここはコメント行です
DirectoryIndex index.html "# 行の途中コメントは避けましょう"
.htaccess におけるコメントアウト

文字コードと改行

.htaccess の文字コードはUTF-8(BOM無し)、改行コードはLFを設定し、ファイルの最終行には空行を入れる必要があります。ただし .htaccess が日本語などの全角文字を含まず、半角英数字だけである場合は文字コードは Shift-JIS や EUC-JP などでも問題ありません。文字コードや、改行コードが誤っている場合は、500 internal server error が発生するため注意が必要です。

特に Windows 環境では、プレーンな .htaccess を作成するためにテキストエディタが必要になります。メモ帳では保存時の文字コードで UTF-8 が選択できますが、BOMが付与されてしまいます。また、ワードパッドではリッチテキスト形式となり、余計なバイナリ情報が付与されるため .htaccess が機能しないため注意しましょう。

また、改行は構文の終端として認識されますが、行末に \ をつけて改行すると構文が次の行に継続しますが、あまり一般的な表記ではありません。途中改行を行う場所によってはエラーになるため、特に必要でない限りは途中改行も避けた方が無難です。

# ErrorDocument 404 404error.html を途中で改行する
ErrorDocument 404 \
404error.html

# 最終行の後には空行を入れましょう
.htaccess における改行

httpd.conf

httpd.conf は .htaccess の上位ファイルです。そのため .htaccess では httpd.conf で許可されている命令のみ指定できます。許可されていない命令を指定した場合、無効になるか 500 internal server error が発生します。何が許可されているかは、利用しているサーバの公式ヘルプを確認して下さい。

もしも httpd.conf を確認できる場合は、 "AllowOverride" ディレクティブを探してみましょう。デフォルトの設定では、httpd.conf に AllowOverride ディレクティブが含まれていますが、見つからない場合は、追記することで設定できます。

# None は .htaccess による設定をすべて無効にする
<Directory />
  AllowOverride None
</Directory>
httpd.conf に含まれている .htaccess の設定例

転送と有効範囲

.htaccess をWebサーバへ転送する際はアスキーモードで転送します。転送後は .htaccess のパーミッションを "644(rw-r--r--)" に設定します。ただし、共有サーバでは、"604(rw----r--)" の場合もあります。

.htaccess の設定は、配置したディレクトリ以下に対して有効になります。そのため、Webサイト全体に対して設定を有効にしたい場合は、ルートディレクトリに配置しましょう。階層別に分けて配置した場合、より深い階層に配置した .htaccess の設定が優先されます。

/www
|-- .htaccess         # Webサイト全体に対して有効 ・・・ A
|-- index.html        # Aの設定が有効になる
|
|-- /contents
|   |-- contents.html # Aの設定が有効になる
|
|-- /blog
    |-- .htaccess     # blog配下に対して有効 ・・・ B
    |-- blog.html     # Bの設定が有効になる
階層別における .htaccess の有効範囲

上記の例では .htaccess A と .htaccess B で同じ設定項目を使用している場合に限ります。同じ設定項目を使用している場合、より深い階層に配置した .htaccess の設定で上書きされますが、その他の設定項目は上位の階層の設定が有効になります。

階層別に同じ設定項目がある場合

# .htaccess Aの設定
RewriteEngine On
RewriteRule index1.html index2.html

# .htaccess Bの設定
RewriteEngine On
RewriteRule index1.html index3.html
同じ設定項目は上書きされる

上記の例では RewriteRule が .htaccess A と .htaccess B に書かれています。.htaccess に同じ設定項目がある場合、より深い階層の設定が有効になるため /blog にアクセスすると .htaccess A の設定が .htaccess B の設定で上書きされます。そのため blog/index1.html にアクセスした場合 index3.html に書き換わります。

階層別に異なる設定項目がある場合

# .htaccess Aの設定
DirectoryIndex index.html

# .htaccess Bの設定
RewriteEngine On
RewriteRule index1.html index2.html
異なる設定項目は継承される

上記の例では異なる設定項目が .htaccess A と .htaccess B に書かれています。.htaccess に異なる設定項目がある場合 .htaccess A の設定が .htaccess B にも継承されます。

各階層の設定が有効になる場合

# .htaccess Aの設定
RewriteEngine On
RewriteRule index1.html index2.html

# .htaccess Bの設定
RewriteEngine On
RewriteRule index1.html /index1.html
書き換え後の階層の設定が有効になる

上記の例ではやや複雑な設定になっています。blog ディレクトリの blog/index1.html にアクセスすると .htaccess B の設定が有効になり、ルートディレクトリの index1.html に書き換わります。書き換え後のパスに / がついていると絶対パスになり、ルートディレクトリになります。

ルートディレクトリの index1.html に書き換わると .htaccess A の設定が有効になり、最終的には index2.html に書き換わります。このように、ディレクトリを跨ぐ書き換えが行われると書き換わった先のディレクトリで有効な .htaccess の設定が改めて適用されます。.htaccess を階層別に分けて配置する場合は、適用される有効範囲について注意しましょう。

正規表現

.htaccess では、正規表現による指定が可能です。正規表現とは、いくつかの文字列を1つの形式で表現する記述方法です。例えば、index1.html と index2.html がある場合、以下の正規表現で表すことができます。

index(1|2).html

"(" , ")" で囲んだ部分は1つのグループとなり、複数の文字を1つの単位として扱うことができます。"|" はOR条件を表すため、正規表現の意味としては "index" に続く文字が "1" または "2" となります。このように、正規表現を使用すればファイル名などを柔軟に指定することが可能です。

基本的な正規表現
文字説明
.任意の1文字 にマッチします。
+直前の文字が 1回以上 繰り返す場合にマッチします。
"go+gle" は "gogle" や "google" にはマッチしますが "ggle" にはマッチしません。
*直前の文字が 0回以上 繰り返す場合にマッチします。
"go*gle" は "gogle" や "google" や "ggle" にマッチします。
?直前の文字が 0個か1個 ある場合にマッチします。
"go?gle" は "gogle" や "ggle" にマッチしますが "google" にはマッチしません。
^直後の文字が行の 先頭 にある場合にマッチします。
"^google" は行の先頭に "google" の文字がある場合にマッチします。
$直前の文字が行の 末尾 にある場合にマッチします。
"google$" は行の末尾に "google" の文字がある場合にマッチします。
|選択肢を区切るために使われます。
"google|googol" は "google" と "googol" にマッチします。
"goog(le|ol)" と表記しても同様の結果を得られます。
\直後の "正規表現において特別な意味を持つ" 文字を エスケープ する。
"go\+gle" は "go+gle" にマッチします。
正規表現における "+" の意味を失い "+" 文字として扱います。
[]角括弧に含まれる文字のいずれか1つにマッチします。
[abcXYZ01] は "a" , "b" , "c" , "X" , "Y" , "Z" , "0" , "1" にマッチします。

角括弧内の文字を "-" を使って範囲指定のマッチもできます。
[a-cX-Z0-1] は "a" , "b" , "c" , "X" , "Y" , "Z" , "0" , "1" にマッチします。

角括弧内の先頭に "^" を使って含まれない文字のマッチもできます。
[^abc] は "a" , "b" , "c" 以外の文字にマッチします。
()文字の集合を1つのグループにまとめて扱うことができます。
(google)+ は "google" を1つの単位として評価するため "google" にマッチします。
また、マッチング文字列は後述する "後方参照" として利用できます。
{n,m}直前の文字、またはグループの桁数を指定してマッチ判定します。
a{3} は a が3桁、つまり "aaa" にマッチします。
a{3,5} は a が3~5桁、つまり "aaa" , "aaaa" , "aaaaa" にマッチします。
a{3,} は a が3桁以上にマッチします。

正規表現には基本的な表記の他に定義済みのクラスがあります。一部の定義済みクラスは "[:" と ":]" の特殊な括弧を使用することで表記します。

定義済みの正規表現クラス
文字対応する表現説明
\d[0-9]すべての数字
\D[^0-9]すべての数字以外の文字
\s[ \t\f\r\n]垂直タブ以外のすべての空白文字
\S[^ \t\f\r\n]すべての非空白文字
\w[a-zA-Z_0-9]アルファベット、アンダーバー、数字
\W[^a-zA-Z_0-9]アルファベット、アンダーバー、数字以外の文字
[:digit:][0-9]すべての数字
[:lower:][a-z]小文字のアルファベット
[:upper:][A-Z]大文字のアルファベット
[:alpha:][a-zA-Z]アルファベット
[:xdigit:][0-9A-Fa-f]16進数で使われる数字とアルファベット
[:alnum:][a-zA-Z0-9]アルファベットと数字
[:punct:][.,!?:...]句読点文字
[:cntrl:](なし)制御文字
[:blank:][ \t]空白文字とタブ
[:graph:][^\n\r\f\v]印字文字
[:space:][ \t\n\r\f\v]改行を含む空白文字

正規表現が使用できるディレクティブ

.htaccess では正規表現が使用できますが、すべてのディレクティブで正規表現が使用できるわけではありません。使用できるディレクティブは "Match" という単語が名前に含まれているディレクティブ(例えば FilesMatchなど)や、次章以降の RewriteRuleディレクティブ、RewriteCondディレクティブでは正規表現が使用できます。

Apache のモジュールと .htaccess で利用可能なディレクティブ

Apache の使用可能なモジュールの中から .htaccess で利用可能なディレクティブを説明します。Apache は、基本的に組み込まれている "コア機能" と呼ばれるディレクティブと、モジュールを追加することで機能が拡張されたディレクティブがあります。モジュール名は、習慣的に mod_XXX (XXXは機能の概要名)という名前になっています。

Apache は必要最低限の機能を http_core.c にまとめ、その他の付加的な機能は個別にモジュールとして実装しています。モジュールの追加や削除を行うことで、機能の最適化が可能です。以下は、Apache のモジュールアーキテクチャの概念図です。

Apacheのモジュールアーキテクチャ
Apache のモジュールアーキテクチャの概念図
(参考:小山 浩之(著)「Apacheモジュール プログラミングガイド」P16 図1-1)

モジュールの追加方法は、"静的リンク" と "動的リンク" の 2 種類あります。静的リンクは、Apache の実行ファイルにモジュールを組み込む方式です。動的リンクは、必要に応じてモジュールファイルを機能を呼び出す方式です。動的リンクの機能を利用するためには、mod_so モジュールを静的リンクしておく必要があります。また、動的リンクは静的リンクよりも負荷がかかりますが、Apache の再起動のみでモジュールを追加・削除できるメリットがあります。逆に、静的リンクは高速にモジュールを呼び出せますが、Apache の再コンパイルを行う必要があります。レンタルサーバーを利用している場合は、Apache を操作する権限がない場合が多いため、利用できるモジュールが制限される可能性があります。

もしも httpd コマンドの実行許可を持つユーザである場合は、Apache に組み込まれているモジュールを確認できます。httpd コマンドに -M オプションを付けることで静的リンクのモジュール (static) と 動的リンクのモジュール (shared) が表示されます。

# httpd コマンドで利用可能なモジュールを確認する
[root@ ~]# /etc/init.d/httpd -M
Loaded Modules:
core_module (static)
mpm_prefork_module (static)
http_module (static)
so_module (static)
authn_file_module (shared)
authn_dbm_module (shared)
・・・(中略)・・・
Syntax OK

[root@ ~]# 
Apache の利用可能なモジュールを確認する例

ただし、httpd -M コマンドでは、サードパーティー製のモジュールも一緒に表示されるため、Apache が採用している静的リンクのモジュールのみ表示したい場合は、httpd -l コマンドを使用します。

# httpd コマンドで利用可能なモジュールを確認する
[root@ ~]# /etc/init.d/httpd -l
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
・・・(中略)・・・

[root@ ~]# 
Apache の利用可能なモジュールを確認する例

モジュールとディレクティブ一覧

HTTP環境変数

ブラウザでサーバにアクセスする際、HTTPリクエストヘッダに各種の情報を含めて送信しています。HTTPリクエストヘッダの情報は "%{環境変数名}" と指定することで RewriteCond で利用できます。

RewriteCond で利用できる HTTP 環境変数
グループ環境変数名
ヘッダ環境変数
HTTP headers
HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, HTTP_FORWARDED, HTTP_HOST, HTTP_PROXY_CONNECTION, HTTP_ACCEPT
サーバー環境変数
server internals
DOCUMENT_ROOT, SERVER_ADMIN, SERVER_NAME, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL, SERVER_SOFTWARE
リクエスト環境変数
connection & request
REMOTE_ADDR, REMOTE_HOST, REMOTE_PORT, REMOTE_USER, REMOTE_IDENT, REQUEST_METHOD, SCRIPT_FILENAME, PATH_INFO, QUERY_STRING, AUTH_TYPE
システム日付・時刻変数
date and time
TIME_YEAR, TIME_MON, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC, TIME_WDAY, TIME
その他
specials
API_VERSION, THE_REQUEST, REQUEST_URI, REQUEST_FILENAME, IS_SUBREQ, HTTPS

後方参照

後方参照とは、正規表現の "(" , ")" に囲まれた条件にマッチングした文字列を "後方" で "参照" できる方式です。以下の例は、マッチングした文字列を "$1" で参照しています。

# Rewriteエンジンを起動
RewriteEngine On

# URLからwwwは取り除くが、ディレクトリ名やファイル名は後方参照で使いまわす
RewriteCond %{HTTP_HOST} ^www\.murashun\.jp
RewriteRule ^(.*)$ https://murashun.jp/$1 [R=301,L]
後方参照を利用してURLを正規化する

RewriteRuleの後方参照

RewriteRule で後方参照を利用する場合は "$n" で表記します。( n には 0 ~ 9 の数字が入ります。) 後方参照は、複数の条件がある場合でも利用できます。マッチング条件が複数ある場合は、左側から $1, $2 というように、どの条件にマッチングした文字列を参照するか選択できます。ただし、$0$1 は同じ値を示します。また、10 を超える後方参照は使用できません。$10 と記述しても "$1""0" の文字列として認識されます。

# Rewriteエンジンを起動
RewriteEngine On

# /blog/foo/bar → /foo/bar に変換される
RewriteRule ^/blog/(.*)/(.*)$ /$1/$2
#                   $1   $2
RewriteRuleにおける後方参照

RewriteCondの後方参照

 RewriteCond で後方参照を利用する場合は "%n" で表記します。( n には 1 ~ 9 の数字が入ります。) 表記する記号が RewriteRule と異なり % であることと、%0 は使えないことに注意して下さい。その他の使い方は RewriteRule と同様です。

# Rewriteエンジンを起動
RewriteEngine On

#                                 %1   %2
RewriteCond %{REQUEST_FILENAME} ^(.*)/(.*)/index.html$
RewriteRule ^/blog/(.*)/(.*)$ /$1/%1/$2/%2
#                   $1   $2
RewriteCondにおける後方参照

まとめ

.htaccess を使って実現できることは非常に多くあります。独自の構文を組み上げてオリジナルの黒魔術を完成させることも一興ですが、代々伝わる使い古されたレシピを使うことをおすすめします。深みにはまってダークサイドに堕ちないように気をつけて下さい。

代表的なレシピは.htaccess の設定レシピ集を参照して下さい。