サイトをリニューアルしたときに発生する作業が .htaccess(エイチティーアクセス) によるリダイレクト処理です。
.htaccess とは Apach(アパッチ)と呼ばれるWebサーバーの設定を行うためのファイルです。
Laravel にも public ディレクトリ配下にありますよね。
正規表現なども書くため、デザイナーよりもプログラマーが担当することが多かったりします。
今回は .htaccess の書き方についてエントリーします。
しかし、 Nginx では基本的に .htaccess が使えない ので注意が必要です。
INDEX
- 構文の解説
- IfModule mod_rewrite.c ~ /IfModule
- RewriteEngineディレクティブ
- RewriteBaseディレクティブ
- RewriteRuleディレクティブ
- RewriteCondディレクティブ
- .htaccess サンプル集
- ドメインの www のあり・なしの統一(URLの正規化)
- 「http://」 から 「https://」 にリダイレクト(常時SSL化)
- ファイル単位でリダイレクト(301リダイレクト)
- ディレクトリをリダイレクト(301リダイレクト)
- PC・スマホサイトの振り分け
- ページが存在しなかったら「404エラーページ」へ飛ばす
- URLの最後を統一するためのリダイレクト(URLの正規化)
構文の解説
まずは .htaccess によるリダイレクト処理の記述を見てみましょう。
そこから各設定(ディレクティブ)ごとに解説していきます。
サンプル(リダイレクト処理)
実例
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 の値は使われることがありません。
# /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 /
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 |
正規表現パターンがマッチするかどうかを評価するときに大文字と小文字を区別しません。
|
OR |
RewriteCondの条件を「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"。 |
$_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>
・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 を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。