メニューを開く

2021/06/06

Apache ~ .htaccess設定方法と使い方 リダイレクト ~

 

.htaccessファイルは、分散設定ファイルとも呼ばれ、Webサーバーの挙動を設定することができるファイルのひとつで、WebサーバーとしてApacheが使用されていて、管理者が.htaccessファイルの設置を許可していれば使用することができます。

設定方法


Apacheは、http.confにディレクティブという命令を記述することで設定しますが、http.confは管理者にしか編集できなくなっています。それに対して、.htaccessファイルは各ユーザーがディレクトリ単位に設定することができます。ファイルの構文は、主設定ファイルのhttp.confファイルと同じです。
注意事項
  • 基本的に、http.confファイルにアクセスできない場合以外は極力使用しない
  • FTPで転送する場合、ASCIIモードまたは、テキストモードを使用する
  • Windowsで編集する場合、一旦htaccess.txtなどに置き換え、サーバーに配置後にリネームする
  • 設置されたディレクトリと配下ディレクトリ全てに影響する
  • 構文誤りや管理者が許可していないディレクティブを使用した場合、該当ディレクトリ配下のファイルアクセスが、500 Internal Server Errorになる
  • 最終行には、改行を入れる

使い方

いろんな使い方ができるみたいですが。ざっくりとですが、こんなことができるみたいです。勉強しながら少しずつ記事にしていきたいと思っています。

使い方概要
  • セキュリティ関連
  • エラーページ制御
  • キャッシュ制御
  • ページ表示の高速化
  • 多言語対応
あれっ、よく見れば、リダイレクトが抜けていました。
ということで、今回はリダイレクトについて記事を書きます。

リダイレクト
リダイレクトとは、ドメインやページのURL、ファイル名やディレクトリ名が変更された時に使われるURLの自動転送処理のことです。.htaccessでファイルを用いたリダイレクトには、RedirectディレクティブとRewriteRuleディレクティブを用いた方法があります。

Redirectディレクティブ
Redirectディレクティブを用いて、URLの自動転送するための構文です。
Redirectディレクティブの詳細はこちらを参照。
構文
Redirect [status] URL-Path URL

URL-Path :転送元URL

      URL-Pathは、相対パスでなく、絶対パスで指定する

URL        :転送先URL

      URLは、スキーム名で始まる絶対URLで指定する

[status]   :キーワードを指定することでHTTPステータスコードを返せる

      キーワード HTTPステータス

                                      コード

                permanent      301     リソースを恒久的に移動した際に指定

                temp              302     リソースを一時的に移動した際に指定

                seeother         303     リソースを他のもので置き換えた際に指定

                gone               304     リソースが恒久的に削除した場合に指定

Redirectディレクティブは、パスが完全一致した場合に処理されます。正規表現を用いたマッチングを行いたい場合には、RedirectMatchディレクティブを利用します。


301リダイレクト

サイトやページを恒久的に移転先へ転送することで、ユーザーや検索エンジンが正しいページにたどり着くことができるようにする方法です。例えば、301 リダイレクトを使用してページの URL を変更するを参考にすると次のような場合です。
・サイトを新しいドメインに移転済みで、可能な限りシームレスに移行したい場合
・ユーザーが複数の異なる URL からサイトにアクセスする場合
・2つのウェブサイトを統合し、使わなくなったURLへのリンクが正しいページにリダイレクトされるようにしたい場合
301リダイレクトで、検索エンジンにリンクの評価が引き継がれて、サイトの評価をある程度は保つことが出来て、SEO効果があるとされているそうです。
Redirectディレクティブを使った転送の場合には、status引数にpermanentを指定することで301リダイレクトになります。つまり、次の構文のように記載することで、転送元URL-Path(/)を転送先URL(http://www.example.co.jp/)にリダイレクトすることが出来ますが、転送先に対応するファイルが存在しない場合には、HTTP 404 Not Foundになります。
記述例
Redirect permanent / http://www.sample.co.jp/
また、次の構文のように記載することで、特定ディレクトリ(/srce/)を別ディレクトリ(http://www.sample.co.jp/dest/)に転送することが出来ます。この場合も同様に、転送先に対応するファイルが存在しない場合には、HTTP 404 Not Foundになります。
記述例
Redirect permanent /srce/ http://www.sample.co.jp/dest/

さらに、次の構文のように記載することで、特定ページ(/srce/test.html)を別ページ(http://www.sample.co.jp/dest/test.php)に転送することが出来ます。

記述例
Redirect permanent /srce/test.html http://www.sample.co.jp/dest/test.php

RedirectMatchディレクティブ
RedirectMatchディレクティブは、Redirectディレクティブと機能的には、ほぼ同じですが、正規表現を用いてマッチングするところが異なります。
構文
RedirectMatch [status] regx URL
例えば、以下のように記述することによって、GIFファイルを全て別サーバーの同様な名前のJPEGファイルにリダイレクトすることが出来ます。
記述例
RedirectMatch (.*)\.gif$ http://www.anotherserver.com$1.jpg

詳細は、Apache RedirectMatchディレクティブを参照。 既存サイトのURLを変更する方法は、URLの変更を伴うサイト移転の例を参照。


.htaccessが使えない場合

また、利用している環境で、.htaccessによるリダイレクトが使えない場合には、次の方法でリダイレクトする方法もあります。

mata refresh
<head>内で次のように記載することで、meta要素のhttp-equiv属性に”refresh"を設定すし、リダイレクトを指定できます。content属性で指定した秒数後に指定したURLへリダイレクトされます。
記述例
<meta http-equiv="refresh" content="秒数; URL=http://dest-domain/"
>

PHP header()関数

PHPを使って転送先にリダイレクトさせるには、header()関数Locationヘッダーを使用し、header()関数以下のスクリプトが実行されないようにexit()関数を使ってスクリプトを終了させます。

記述例
<?phpheader('HTTP/1.1 301 Moved Permanently');
header('Location: http://sample.co.jp/');
exit();
?>

 

mod_rewriteを使用したリダイレクト

サーバーの拡張機能mod_rewriteの機能を使用することができれば、RewriteRuleディレクティブを使ったリダイレクトを設定することができます。

記述例
RewriteEngine On
RewriteBase /
RewriteRule 転送元ファイル正規表現 転送先URL [フラグ]
RewriteEngine:mod_rewriteの機能のOn/Off を指定
デフォルトの値は、OffなのでURLの書き換え処理を行うには、Onにする

RewriteBase:RewriteRuleディレクティブで指定するリダイレクト先URLで書き換える基準となるディレクトリを相対パスで指定
RewriteRuleの転送先を相対パスで記述した場合にのみ適用され、絶対パスで指定している場合には不要で省略した場合は、.htaccessを配置したディレクトリからの相対パスが適用される

RewriteRule:具体的なURLの書き換えルールを記述
1番目のパラメータである正規表現にマッチした場合には、2番目のパラメータであるURLに書き換えられる

フラグ:省略可能、301リダイレクトにするには、R=301を指定する必要がある
合わせて指定される「L」はURLの書き換え処理を終了を意味する

例えば、特定のページから特定ページへのリダイレクトは、以下の記述例のように記述します。

記述例

RewriteEngine On
RewriteRule ^srce/(.*)$ http://www.sample.co.jp/dest/$1 [R=301,L]

IfModuleディレクティブ

次のように記述することで、使用している環境でmod_rewrite が利用できるかどうかを確認し、利用できない場合には、<IfModule mod_rewrite.c> ~ </IfModule>の中のコードが適用されません。
記述例
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ...
</IfModule>

 

構文
<IfModule [!]module-file|module-identifier> ... </IfModule>
IfModuleディレクティブは、モジュールが存在する場合または存在しない場合に処理されるディレクティブを指定することができ、モジュールが存在しない条件の場合には、!をモジュールのファイル名の前に付けることで、そのモジュールが存在しない場合に処理されます。

module引数は、モジュール識別子または、コンパイルをした時のモジュールのファイル名で、rewrite_moduleは識別子でmod_rewrite.cはファイル名です。

mod_rewriteが利用できない環境ではmod_ rewriteのコードを記述するとエラーが発生します。利用できるかわらない場合、IfModuleディレクティブを使いmod_rewriteが使えるかを確認できます。

利用できることがわかっている場合には不要で、Apacheのマニュアルの<IfModule> ディレクティブには、「特定のモジュールの存在に関わらず動作する設定ファイルの原本が必要な場合にのみ、このセクションを使用してください。通常の動作では、ディレクティブを<IfModule>セクションの中に入れる必要はない。」ということが記載されています。

RewriteCond ディレクティブ
RewriteCond ディレクティブは、書き換えルールを実行するための条件を定義します。RewriteCondに記述した条件を満たした場合にのみ、直後のRewriteRuleディレクティブの書き換えが行われ、条件を満たさない場合には、直後のRewriteRuleディレクティブは実行されません。

RewriteCondディレクティブは、RewriteRuleディレクティブの前に1つ以上設置することができます。複数設置する場合は、オプションによってOR条件として処理するかを指定できます。オプションを省略した場合には、AND条件として処理されます。
構文
RewriteEngine On
RewriteCond 文字列 条件パターン [オプション]
RewriteRule 条件 置換文字列

オプション
RewriteCondで使用できるオプション

オプション  意味
[OR]    連続する RewriteCond のいずれかが true の場合に実行します。
       省略時は、AND条件として処理され、連続するRewriteCondが
       全てtrueの場合に実行します。
[NC]      条件を評価する時、大文字小文字を区別しません。
       指定しないと大文字小文字を区別します。
ORとNCをどちらも指定したい場合は[OR,NC]とカンマ区切りで指定します。

後方参照
RewriteCondの条件パターンでは、正規表現で括弧を使って一致した値は、変数を使って再利用できます。RewriteCondで指定したパターンを参照する場合には、%nを使い、括弧が複数ある場合には、左から%1、%2というように指定します。

RewriteRuleディレクティブでも後方参照を利用できます。RewriteRuleディレクティブの場合は、通常の正規表現の後方参照と同様に$nを使用します。

環境変数
mod_rewriteでは、環境変数という特別な変数を利用でき、%{環境変数名}と指定することで利用できます。

環境変数         値と意味
HTTP_HOST       リクエスト先のDNS名の情報。
HTTP_REFERER      参照元のURL情報
HTTP_ACCEPT        ブラウザがサポートするメディア、MIMEタイプの情報
HTTP_USER_AGENT  ユーザのブラウザや端末情報
HTTPS          HTTPSであればon、そうでなければoffが返却される
QUERY_STRING    クエリ文字列
SERVER_ADDR     サーバーのアドレス
SERVER_PORT           サーバーのポート番号
PATH_INFO      ファイル名とクエリ文字列の間にあるパス情報
REMOTE_ADDR    ユーザのIPアドレス情報
REMOTE_USER    リモートユーザー名
REMOTE_HOST    リモートホスト名
THE_REQUEST    リクエスト文字列
REQUEST_URI     リクエストされたURIの情報とクエリ文字列
REQUEST_FILENAME リクエストされたファイル名(絶対パス)
SCRIPT_FILENAME  実行するスクリプトの絶対パス情報
DOCUMENT_ROOT  ドキュメントルートのパス情報
TIME_YEAR       年
TIME_MON      月
TIME_DAY       日
TIME_WDAY      曜日(0:日~6:土)
ENV:環境変数名    %{ENV:...}式を指定し環境変数に基き条件分岐可能

 

条件パターンで使用できる演算子
RewriteCondでは、条件に一致するパターンをPerl互換の正規表現で指定することができます。下記の記述例は、リクエストされたファイルもリクエストされたディレクトリも存在しないという条件になります。
記述例
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

利用できる
演算子の例   意味
!      否定
<       テスト文字列より大きい場合はtrue
>       テスト文字列より小さい場合はtrue
=       テスト文字列と等しい場合はtrue
<=       テスト文字列以上の場合はtrue
>=       テスト文字列以下の場合はtrue
-d         ディレクトリが存在する場合はtrue
-f        ファイルが存在する場合はtrue
-s        ファイルが存在し、サイズが0でない場合はtrue

RewriteRuleディレクティブ
RewriteRuleディレクティブは、URLの書き換えを行うディレクティブで、条件パターンに一致するURLを、その後の置換文字列で書き換えます。条件パターンは、Perl互換の正規表現で指定することができます。
構文
RewriteRule 条件パターン 置換文字列 [フラグ]
条件パターン :URLとマッチさせる部分
        正規表現を利用することができる
置換文字列  :URLと条件パターンがマッチした場合に、行う処理を指定する
[フラグ]   :挙動を制御するためのオプションを指定できる
        複数のフラグを指定する場合には、カンマ区切りで指定する
フラグ    別名    意味
R           redirect        指定したURLにリダイレクトする
[=code]           [R=301]のようにレスポンスコードを指定する
             ことができる
             指定しない場合は、302 Moved Temporarilyで
             リダイレクトされる
             temp(302)、permanent(301)、seeoth
             er(303)のシンボル名も指定できる
F     forbidden        ステータスコード 403 Forbiddenを返す
             RewtiteCondに設定した条件で、Webサーバー
                                  へのアクセスを禁止する場合などに指定する
G     gone          ステータスコード 410 Goneを返す
             ユーザーに、存在しないページにアクセスして
                                  いることを通知する時に指定する
P      proxy         ルールにマッチしている場合には、書き換えた
             URLをプロキシ要求とみなし、リバースプロキ
             シとして動作する
             このフラグを使用する場合には、mod_proxy
             が組み込まれている必要がある
L     last         ルールにマッチしている場合は、URLの書き
             換え処理を終了し後続のルールを適用しない
             但し、.htaccessでは、Lフラグが有効になら
                                   ない
N     next          一連の書き換え処理のルールを先頭のルール
                                   から再度実行する
              既に書き換えられたURLが対象となる
              本フラグを指定する場合は、書き換え処理が
                                    無限に実行されないよう適切に終了条件を設
               定する必要がある
C      chain           ルールにマッチしている場合は、後続のルー
                                    ルを適用する
               ルールにマッチしていない場合、後続のルー
                                    ルは全て適用されない
T=MIME-  type=MIME-   ルールにマッチしている場合は、指定した
type         type               MIMEタイプをContent-Typeヘッダに設定
                                    する
NS           nosubreq        Webサーバー内で発生するサブリクエスト
                                    には、ルールを適用しない
             ユーザーから末尾がスラッシュのURLが指
                                    定された際に、DirectoryIndexディレクテ
                                    ィブで指定したファイルに対するサブリク
                                    エストが発生するが、そのサブリクエスト
                                    にルールを適用しない場合などに使用する
NC      nocase        大文字小文字を区別せずにルールを適用
                                    する
QSA    qsappend      書き換え前のURL及び置換文字列にそれぞ
                                    れクエリ文字列が存在する場合には、置換
                                    文字列の末尾にアンパサンドと書き換え前
                                    のURLに指定されたクエリ文字列を追加す
                                    る
             本フラグを指定しない場合には、クエリ文
                                    字列は置換文字列で上書きされる
NE     noescape      書き換え時のURLエスケープを抑制する
             通常、パーセント(%)やセミコロン(;)など
                                    の特殊文字は、16進表現の“%25”、“%3b”
                                    にエスケープされるが本フラグを指定した場
             合には、エスケープされない
PT     passthrough  URLの書き換え後、他のモジュールに制御を
                                    渡す書き換えたURLに対し、Aliasディレクテ
                                    ィブ、ScriptAliasディレクティブおよびRed
                                    irectディレクティブなどを使用する場合に指
                                    定する
S=num    skip=num     ルールにマッチしている場合、数値に指定し
                                    た数の後続のルールの適用をスキップする
E=環境   env=環境      ルールにマッチしている場合、指定した任意
変数:値       変数:値       の環境変数に設定する
             値には、置換文字列と同様に、$nおよび%n
             も指定できる

RewriteRuleを複数記述する場合
RewriteRuleを複数記述した場合、処理は先頭行から条件に一致する行を探索する。条件に一致した場合は、先頭行に戻り、再度条件に一致する行を探索する。

.htaccessファイルでURLの書き換えを行うと、書き換えが終わった後にもう一度書き換え設定を上から順に適用し、書き換えの必要がないかをチェックし、書き換える必要が無くなるかループでエラーになるまで処理が続行されます。
.htaccessでは、再探索が優先されるので、無限ループを防ぐには、通常RewriteCondを使用します。

index.htmlなしに統一する場合
インデックスファイルにアクセスがあった場合に、/ディレクトリに301リダイレクトさせる方法です。
記述例
RewriteEngine On
RewriteCond %{THE_REQUEST} ^.*/index\.html
RewriteRule ^(.*)/index\.html$ http://%{HTTP_HOST}/$1 [R=301,L]
%{THE_REQUEST} には、HTTPリクエスト(例:GET /index.html HTTP/1.1)が入っていて、条件パターン ^.*/index\.html にマッチすれば、次の行のRewriteRuleが適用され、/index.htmlが削除されます。

サーバーの環境によっては、この設定を記述するとリダイレクトによりphpMyAdminにコントロールパネルからアクセスできなくなる場合があるらしいです。ユーザー名とパスワードを入力しても、エラーも表示されずにログイン画面のままとなるようです。

その場合には、phpMyAdminのディレクトリ(/mysqladmin/)を除外します。
記述例
RewriteEngine On
RewriteCond %{REQUEST_URI} !(^/mysqladmin/)
RewriteCond %{THE_REQUEST} ^.*/index\.(html|php)
RewriteRule ^(.*)index\.(html|php)$ http://%{HTTP_HOST}/$1 [R=301,L]

 

httpsに統一する場合
以下の記述例は、httpで始まるURLへのアクセスをhttpにリダイレクトさせる方法です。
記述例
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

httpに統一する場合
以下の記述例は、httpsで始まるURLへのアクセスをhttpにリダイレクトさせる方法です。
記述例
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

メンテナンスページにリダイレクトさせる場合
Webサイトのメンテンナスをしていて、どのURLにアクセスされても「メンテナンス中」というメンテナンスページ(mainte.html)を表示するようにしたい場合には、.htaccess に以下の記述例のように記述することでリダイレクトさせることが出来ます。
最終行に記載しているHeaderディレクティブでは、メンテナンス終了予定時刻を設定しています。
記述例
ErrorDocument 503 /mainte.html
RewriteEngine On
RewriteCond %{REQUEST_URI} !=/mainte.html
RewriteCond %{REMOTE_ADDRES} !=xxx.xxx.xxx.xxx
RewriteCond %{REQUEST_FILENAME} !\.(css|jpe?g|gif|png|js)$
RewriteRule ^.*$ - [R=503,L]
Header set Retry-After "Sun, 06 Jun 2021 9:00:00 GMT"

緊急メンテナンスなどの場合には、以下の記述例の記述を .htaccessに追記することで、ユーザーに「During emergency maintenance.」というメッセージを表示し、検索エンジンには503のステータスコードを返すことができます。
記述例
ErrorDocument 503 "During emergency maintenance."
RedirectMatch 503 .*

エラーページの変更方法
ErrorDocumentディレクティブを使うことによって、エラードキュメントの表示方法の設定をすることができます。
構文
ErrorDocument error-code document
error-codeには、ステータスコード。documentには、表示するテキストまたはファイルへのパスを指定することができます。

ErrorDocumentディレクティブを使うことによって、問題やエラーが発生した時に以下のような振る舞いを設定することができます。
  • 問題やエラー処理をするために、自サーバ内のURL-pathへリダイレクト
  • 問題やエラー処理をするために、外部URLへリダイレクト
  • 自分で指定したメッセージを表示
  • Apache標準のメッセージを表示

自分で指定したメッセージを表示したい場合は、以下の記述例のようにステータスコードの後に、ダブルクォートで囲みメッセージを記述します。
記述例
ErrorDocument 404 "File not found"
自サーバ内のURL-pathにリダイレクトして、問題やエラーの処理をするには、ドキュメントルートからの相対パスで指定します。
記述例
ErrorDocument 404 /file_not_found.html
外部URLへリダイレクトして、問題やエラーの処理をするには、httpなどで始まる完全な URLを指定します。
ただし、外部URLをErrorDocumentに指定することにより、ドキュメントがどこにあるかを通知するために、クライアントにはリダイレクトが送出されます。このため、クライアントは、404のステータスコードを受け取らず、リダイレクトのステータスコードを受け取ります。ステータスコードを使用して、有効なURLであるかどうかを判定しようとするウェブロボットやその他クライアントを混乱させる可能性がありますので注意が必要しましょう。

ErrorDocument 401に外部URLを指定した場合も、クライアントは401ステータスコードを受け取らないため、ユーザーにパスワード入力を要求しなければならないことがわからなくなりるので、ErrorDocument 401を使う場合には、内部サーバーのドキュメントを参照するようにしましょう。

ErrorDocument 404の場合も、同様に内部サーバーのドキュメントを参照するようにして、ユーザーやクローラーにWebサーバーから404のステータスコードを返し、変更した404ページが、検索エンジンのインデックスに登録されないようにしましょう。
ステータスコードの抜粋
ステータス  概要        詳細
コード
 401    Unauthorized    ユーザー認証に失敗
                ID、パスワードのタイプミスなど
 403    Forbidden      指定されたリソースへのアクセス権なし
                 許可されないディレクトリなどへのアクセス
 404    Not Found      指定されたリソースが存在しない
                URLタイプミスなど
 500    Internal Server   サーバーがリクエストを実行できない
      Error        .htaccessなどのサーバ設定ファイルの
                記述ミスなど
 501    Not Implemented   サーバーにリクエストを処理する機能がない
 503    Service Unavailable サービスが利用できない


EmoticonEmoticon