.htaccess まとめ

サイトをリニューアルしたときに発生する作業が .htaccess(エイチティーアクセス) によるリダイレクト処理です。

.htaccess とは Apach(アパッチ)と呼ばれるWebサーバーの設定を行うためのファイルです。

Laravel にも public ディレクトリ配下にありますよね。

正規表現なども書くため、デザイナーよりもプログラマーが担当することが多かったりします。

今回は .htaccess の書き方についてエントリーします。

近年はサーバー動作の高速化の目的で「Nginx(エンジンエックス)」と呼ばれる別のサーバーへの移行も多くなっています。
しかし、 Nginx では基本的に .htaccess が使えない ので注意が必要です。

 

INDEX

 

構文の解説

まずは .htaccess によるリダイレクト処理の記述を見てみましょう。

そこから各設定(ディレクティブ)ごとに解説していきます。

Apache は、httpd.con というテキストファイルに ディレクティブ(命令、コマンドの意味)と呼ばれる専用の命令を記述することで設定します。

 

サンプル(リダイレクト処理)

 

実例

 

IfModule mod_rewrite.c ~ /IfModule

使っているWebサーバ上で「mod_rewrite」というモジュールが利用可能な場合のみ、このタグ内の設定値を読み込むようにできます。

 

RewriteEngineディレクティブ

RewriteEngine ディレクティブはリライト機能を有効または無効に設定します。

on を指定するとリライト機能が有効となり、off を指定するとリライト機能が無効となります。

RewriteRule ディレクティブなどを使ってリライトを実際に行う前に、 RewriteEngineディレクティブを使ってリライト機能を有効にしてください。

 

RewriteBaseディレクティブ

RewriteRule 設定で指定される リダイレクト先URL のベースディレクトリを設定します。

例えば、設定値をサンプルのように「RewriteBase /」と記載すれば、ベースディレクトリは、その .htaccess が配置されたディレクトリ自体となります。

また、RewriteBase の値が利用されるのは「RewriteRule」に指定されたリダイレクト先URLが相対パスで開始する場合のみです。

すなわち、RewriteRule でリダイレクト先に指定した文字列が 「/index.php」であったり、 「http://google.com」であれば、RewriteBase の値は使われることがありません。

RewriteRule 設定で指定される リダイレクト元のURL やサーバ変数 %{REQUEST_URI} の値には一切影響しません。

# /old ディレクトリに .htaccess を設置
# /old/hello.html ⇒ /new/hello.html リダイレクト
RewriteEngine on
RewriteBase /new
RewriteRule ^hello\.html$ hello.html [R=301]

 

RewriteRuleディレクティブ

RewiteRule ディレクティブはリライトをどのように行うのかルールを定義するために使用します。

書式は次のとおりです。

RewriteRule ディレクティブでは最初にクライアントからのリクエストが正規表現パターンとマッチするかどうかを調べます。

マッチした場合は、置換URLで指定した URLにリクエストを置き換えます。

 

正規表現パターンを指定する

リクエストの中の対象の文字列が、指定した正規表現パターンとマッチした場合に URL のリライトが実行されます。


# ^ は先頭とマッチし、$ は末尾とマッチする(正規表現)
RewriteRule ^dir/old.htm$ /new.htm

# 正規表現なし
# この場合は mydir/old.htm や dir/old.htmls などにもマッチする
RewriteRule dir/old.htm /new.htm

 

正規表現パターン まとめ
正規表現パターン 意味 リダイレクトでの例
^ 直後の文字が行の最初のとき ^aaa/ ベースURL以下がaaa/のもの
$ 直前の文字が行の最後のとき aaa.html$ URLがaaa.htmlで終わっているもの
¥文字(バックスラッシュ) エスケープ処理:通常の文字として扱う aaa\.html$ 任意の一文字を表現する正規表現「.」(ドット)と間違うため
!(ビックリマーク) パターンの前に用いることでパターンを否定する命令 !(iPhone|Android.*Mobile) スマホ以外という意味になる
|(パイプ) もしくは (^|&)id=123 id の直前はクエリの先頭もしくは &
id=123(&|$) id=123 の直後はクエリの最後もしくは &
? 直前の文字が0個か1個の場合 bbb.html? bbb.html か bbb.htmll の時 ⇒ クエリー文字列をリライトやリダイレクト先に付加しない
. 任意の一文字 aaa(.*) aaa以下に任意文字列が続くもの全て
* 直前の文字が0回以上繰り返すとき
( ) 文字を1つのグループにまとめる

 

置換URLを指定する

置換 URL の記述方法は次の方法があります。

1)相対パスで指定

相対パスで指定する場合は .htaccess が設置されているディレクトリからの相対パスで指定します。

例えば、/old ディレクトリに .htaccess がある場合に /new/new.html のページ内容でリライトする場合は次のように記述します。


RewriteRule ^old.htm$ ../new/new.htm

相対パスの基準となるディレクトリを RewriteBase ディレクティブで指定することもできます。


RewriteBase /
RewriteRule ^old.htm$ new.htm

 

2)ドキュメントルートからの絶対パスで指定

ドキュメントルートからの絶対パスで指定することもできます。


RewriteRule ^old.htm$ /new/new.htm

 

3)他のサイトの URLを指定

他のサイトの URL を指定した場合にはリライトではなくリダイレクトされます。

その場合、リダイレクト先の URL を http:// などから始まる URL を指定します。


RewriteRule ^old.html$ http://www.example.jp/new/new.html

 

リライトとリダイレクトの違い

リライトというのは、ブラウザのアドレスバーに表示される URL は元のままですが、表示されるページの内容がリライト先のページの内容になります。

それに対してリダイレクトというのはリダイレクト先の URL へ改めてリクエストが送信されるため、ブラウザのアドレスバーに表示される URL もリダイレクト先のものになります。

ただ、 RewriteRule ディレクティブで置換 URL として同じサイトのページを指定した場合でも、フラグ で [R=301] のように指定することでリライトではなくリダイレクトにすることができます。


# リライト
RewriteRule ^old.html$ /new.html

# リダイレクト
RewriteRule ^old.html$ /new.html [R=301]

# リダイレクト
RewriteRule ^old.html$ http://www.example.com/new.html

 

RewriteRule で使うフラグ
フラグ 意味
R 指定したURLにリダイレクトする(Redirect)
例)「R=301」で301リダイレクト
L ここでURL書き換えを中止し、それ以降の書き換えはしないようにする。(Last)

 

RewriteCond で使うフラグ
フラグ 意味
NC 正規表現パターンがマッチするかどうかを評価するときに大文字と小文字を区別しません。


# RewriteCondの第3引数で指定
RewriteCond 対象文字列  条件パターン [NC]

OR RewriteCondの条件を「or」でつなぐ


# RewriteCondの第3引数で指定
RewriteCond 対象文字列  条件パターン [OR]

# 複数のフラグを使う場合はカンマで区切る
RewriteCond 対象文字列 条件パターン [NC,OR]

 

RewriteCondディレクティブ

以下の記述は「常時SSL」の設定になります。

RewiteCond は、自身の直後の RewriteRule を適応する条件を記載します。

多くの場合、サーバ変数や mod_rewrite 特有の変数から得られる文字列を対象とし、正規表現やアパッチ特有の条件記号を用いて、マッチングを行います。

 

.htaccessでよく利用するサーバ変数

サーバ変数は %{変数名} として参照します。下記は、.htaccess で利用される代表的なサーバ変数です。

変数名 取得できる値
HTTP_HOST ホスト名、すなわちドメイン。
例)www.example.com
REMOTE_ADDR ホストのIPアドレス。
REQUEST_URI リクエストにおけるURI。ファイルパス。「/index.php」のように、最初にスラッシュが含まれる点に注意する。また、クエリ文字列は含まれない。
REQUEST_FILENAME ファイルシステム上のファイルパス。(例:/var/www/html/my-site/about.php)ただし、リクエスト時点でファイルが断定できていなければ、REQUEST_URI と同じ値が返される。
HTTPS もしリクエストプロトコルが「https」であれば "ON"、そうでなければ "OFF"。
PHPでのサーバ変数 $_SERVER['REQUEST_URI'] は、クエリ文字列を含みますが、アパッチの %{REQUEST_URI} は、クエリ文字列を含みません。そのため、クエリ文字列は別途 %{QUERY_STRING} を使って参照することになります。

 

.htaccess サンプル集

ドメインの www のあり・なしの統一(URLの正規化)

正規化は「Googleに評価してもらうURLを統一すること」でリンクポピュラリティを集約する、SEO的な設定になります。

www無しのドメインに統一

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com
RewriteRule ^(.*) http://example.com/$1 [R=301,L]
</IfModule>

 

www有りのドメインに統一

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com
RewriteRule ^(.*) http://www.example.com/$1 [R=301,L]
</IfModule>

 

「http://」 から 「https://」 にリダイレクト(常時SSL化)


<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*) https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

 

ファイル単位でリダイレクト(301リダイレクト)

リダイレクト元のパターン指定は、ホスト名直後のスラッシュを含まないURLパスになります。

逆に、リダイレクト先はホスト名直後のスラッシュを含むパスとなります。


<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^blog/old-file.php /blog/new-file.php [R=301,L]
</IfModule>

・301リダイレクト:永続的な転送で評価の引継ぎが行われ、Googleの対応が早い
・302リダイレクト:一時的な転送で評価引継ぎが行われるが、301と比べてGoogleの対応が遅い

 

ディレクトリをリダイレクト(301リダイレクト)

こちらはディレクトリを指定したリダイレクトです。


<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^old-dir/(.*) /some-other-dir/new-dir/$1 [R=301,L]
</IfModule>

 

PC・スマホサイトの振り分け


<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# スマホでPCサイトにアクセスすると「/sp/」ディレクトリにリダイレクト
RewriteCond %{REQUEST_URI} !/sp/
RewriteCond %{HTTP_USER_AGENT} (iPod|iPhone|Android.*Mobile|Windows¥ Phone)
RewriteRule ^(.*)$ sp/$1 [R]

# PCでスマホサイト(/sp/)にアクセスすると、PC向けのトップディレクトリに転送
RewriteCond %{REQUEST_URI} /sp/
RewriteCond %{HTTP_USER_AGENT} !(iPod|iPhone|Android.*Mobile|Windows¥ Phone)
RewriteRule ^sp/(.*)$ $1 [R]
</IfModule>

 

ページが存在しなかったら「404エラーページ」へ飛ばす

事前に「404.html」というファイルを作成してアップロードしておきましょう。

ちなみに、ファイル名は「404.html」でなくてもOKです。


ErrorDocument 404 /404.html

# ページが存在しなかったら「TOP」へ飛ばすケース
ErrorDocument 404 https://www.sample.com/

 

URLの最後を統一するためのリダイレクト(URLの正規化)

URLの最後が下記のように統一されていない場合があります。

  • http://example.com/dir/index.html
  • http://example.com/dir/
  • http://example.com/dir

これを最後に「/」で終わるように処理します。


RewriteEngine on
RewriteCond %{THE_REQUEST} ^.*/index.html
RewriteRule ^(.*)index.html$ https://example.com/$1 [R=301,L]

 
ちなみに「index.html」で統一したい場合


RewriteEngine on
RewriteRule ^$ /index.html [R=301,L]

 
以上です。

本庄マサノリ

仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら

>> Twitter をフォローする

 

-環境構築