Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

Rewrite/Redirect

RewriteとRedirectの違い

  1. Rewrite:URLの書き換えが発生しない
  2. Redirect:URLの書き換えが発生する

設定ファイル

mod_rewriteの仕組みを利用します。
Linux(CentOS)の場合設定ファイルは以下の次のパスになる。/etc/httpd/conf/httpd.conf
今回は上のhttpd.confを少し書き換えて、rewrite/redirectの設定ファイルをincludeさせることを試みる。
httpd.confの最後の行に以下を追記する。Include conf/rewrite.conf
rewrite.confに色々とリダイレクトの記述をして、試してみる。

RewriteEngine,RewriteCond,RewriteRule

apacheの設定ファイル(httpd.conf、今回はrewrite.conf)にRewriteEngine On,RewriteCond,RewriteRuleといった記述をすることでリダイレクト/リライトを実現する。

  1. RewriteEngine On : Rewriteを適用しますという宣言。
  2. RewriteCond : Rewriteを行う条件を指定する。たとえばUserAgentがFireFoxだったら以下のRewriteRuleを適用せよといった指定など。
  3. RewriteRule : Rewriteの適用ルールを記述する。たとえば特定のURIへのアクセスは全部一律で別のURIに置き換えるといった指定など。

Rewrite変数

以下はRewriteCond,RewriteRuleで適用できる変数一覧です。

HTTP headers:
HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPT

connection & request:
REMOTE_ADDR
REMOTE_HOST
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE

server internals:
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE

system stuff:
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

RewriteFlag

以下はRewriteCond,RewriteRuleで適用できるオプション一覧です。

オプション 説明
C(Chain) 次のRuleと条件を結合する。
E(Enviroment) 環境変数の設定。
F(Frobidden) アクセス禁止。クライアントには403Forbiddenのレスポンス。
R(Redirect) クライアントには302のレスポンスを返しリダイレクトをする。
G(Gone) 空になったURLを返す。クライアントには410を渡す。
L(Last) 条件にマッチした場合はそこで判定を終了する。(最終評価)
N(Next) 書き換えが済んだURLを新たなリクエストとして書き換え処理最初のルールから繰り返す
P(Proxy) Proxyモジュールを使用して他のサーバのコンテンツを取得し、内容をクライントに渡す。
S(Skip) ルールがマッチしたら次のN番目のルールをスキップする指示。
T(Type) ターゲットファイルのMIMEタイプを指定する。
NS(NoSubreq) 一時的なURLリクエストの場合のみ条件を評価
NE(NoEscape) 書き換えの結果に対して通常行われるURLエスケープルルーを適用しないようにする。
NC(No Case) 大文字小文字を区別しないパターンの時。
OR(Or) 条件の連結
QSA(Query Sring Append) 置換文字列の中でマッチしたものを書き換えるのではなく、そこにクエリー文字列部分を追加するように書き換えエンジンに強制します。

表記

これ以下は全てサンプル。
重要なのは正規表現と上で上げた変数、オプションの概念。

アクセスを全部切り替える

正規表現の^.*$を使い、全てyahooのTopページを参照させます。
RewriteEngine on
RewriteRule ^.*$ http://www.yahoo.co.jp

特定のパス以下を全て切り替える

特定のパス以下を全てをyahooのTopページを参照させます。
RewriteEngine on
RewriteRule ^/test/.*$ http://www.yahoo.co.jp

特定のパス以下を別のパスに切り替える

正規表現のグルーピング(括弧)と後方参照($1)を利用します。
RewriteEngine on
RewriteRule ^/test/(.*)$ /rewrite/$1

特定のファイルのリクエストのみ切り替える

正規表現のグルーピング(括弧)と後方参照($1,$2)を利用します。
RewriteEngine on
RewriteRule ^/test/(.*)\.(jpg|gif|png|bmp)$ /rewrite/$1.$2

URLの書き換えをさせる

URLを書き換えるようにリダイレクトさせる。
RewriteEngine on
RewriteRule ^/test/(.*)\.(jpg|gif|png|bmp)$ /rewrite/$1.$2 [R]
※[R]の箇所は[R=301]や[R=302]などとしてステータスを付けるとレスポンスコードとして返す。

RewirteRuleを複数適用させる

特定のアクセスを一度リライトさせて、さらにその中の特定のアクセスをさらにリライトさせる。
RewriteEngine On
RewriteRule ^/test/(.*) /rewrite/$1
RewriteRule ^/rewrite/test/(.*) /finish/$1
途中でリライト設定を終了させたい場合は[L]を最後に記述する。

RewriteCondで条件を設定

HTTP_HOSTがmobile-ua.appspot.comじゃなかったらRewriteRuleを適用する。
RewriteEngine On
RewriteCond %{HTTP_HOST} !^mobile-ua.appspot.com$
RewriteRule ^/(.*) /$1

RewriteCondで複数条件を設定

HTTP_HOSTがmobile-ua.appspot.comへのアクセスでUserAgentがDoCoMo,EzWeb,SoftBankという
文字列が含まれている場合にRewriteRuleを適用する。
RewriteEngine On
RewriteCond %{HTTP_HOST} ^mobile-ua.appspot.com$
RewriteCond %{HTTP_USER_AGENT} DoCoMo [NC,OR]
RewriteCond %{HTTP_USER_AGENT} KDDI [NC,OR]
RewriteCond %{HTTP_USER_AGENT} SoftBank [NC]
RewriteRule ^/(.*) /$1
※RewriteCondは何もオプションを指定せず複数記述するとAndの意味になる。

Rewrite変数を使う

リクエストのプロトコルhttpsでなければ、httpsにリダイレクトさせる。
RewriteEngine On
RewriteCond %{SERVER_PROTOCOL} !^https [NC]
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,QSA]

アクセスの拒否

NoRefererの場合はアクセスを拒否する。
RewriteEngine On
RewriteCond %{HTTP_REFERER} $^
RewriteRule ^.*$ [F]

%2F問題

/のエスケープである「%2F」がURLに含まれていると正しくrewriteが動作しないことがある。
例えば /test%2Fword
というアクセスを
/rewrite/script=test%2Fword
というものにrewriteで置き換えるとエラーが発生する。(404)
※直接/rewrite/script=test%2Fwordをたたいてもエラーにはならない。
apacheの2.0.46以降ではAllowEncodedSlashes Onhttpd.confに記述する事で問題が回避可能。
apache1.X系では%2Fを更にもう一度エスケープするなどで回避可能。