.htaccess の書き方（リダイレクト編）

1. **.htaccess の書き方（リダイレクト編）**
2. [.htaccess の書き方（アクセス制御編）](http://qiita.com/shotets/items/17bed9029140a6d925d2)
3. [.htaccess(Apache) の Order Allow,Deny(またはDeny,Allow)について](http://qiita.com/shotets/items/58a69aa15e2adc9f930a)
4. [.htaccess の書き方（スピードアップ編）](http://qiita.com/shotets/items/a5465fb41623cc3dae94)
5. [.htaccess の書き方（設定変更編）](http://qiita.com/shotets/items/cf0783530a1f2809c4d5)


## リダイレクト

### 基本
mod_rewriteが有効な場合だけ処理する。

```apache:.htaccess
<IfModule mod_rewrite.c>
	RewriteEngine on
    :
    ここにリダイレクト処理を記述
</IfModule>
```

パス指定で[R]が無ければリクエスト先を変えるだけ、
[R]がある場合やhttpから指定している場合はリダイレクト、
[R=301]指定している場合は301リダイレクトとなる。

```apache:.htaccess
# アドレスバーを書き換えない（forward）リクエストはindex.phpに
RewriteRule ^(.*)$ index.php
# 302リダイレクト
RewriteRule ^(.*)$ index.php [R]
RewriteRule ^(.*)$ index.php [R=302]
RewriteRule ^(.*)$ https://www.my-domain.com/index.php
# 301リダイレクト
RewriteRule ^(.*)$ index.php [R=301]
RewriteRule ^(.*)$ https://www.my-domain.com/index.php [R=301]
```

ちなみに、301は引っ越しやページの移動など恒久的なリダイレクト、
302はメンテナンスページへのリダイレクトなど一時的なリダイレクト。

### wwwありに統一
リクエストされたホスト名がドメインから始まっている場合に
www有りのドメインにリダイレクトする。

```apache:.htaccess
RewriteCond %{HTTP_HOST} ^my-domain\.com
RewriteRule (.*) https://www.my-domain.com/$1 [R=301,L]
```

汎用的な記述

```apache:.htaccess
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
```

`^` は文字の始まりを意味し、
`.*` は任意の文字の連続、つまり全ての文字列にマッチします。
リクエストされたパスをリダイレクト先でも使いたいので
`(.*)` とカッコでくくり後方参照の$1とすることで
同じパスの違うドメインにリダイレクトできます。

今後もずっとwwwアリで統一するので
R=301（恒久的転送）を指定します。
※指定しない場合、転送先がhttpから始まる場合は302リダイレクトになります。

### SSLに転送
常時SSLが当たり前になってきたので、
この転送はますます必要になってくるでしょう。

```apache:.htaccess
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.my-domain.com/$1 [R=301,L]
```

今後もずっとSSLにするので
R=301（恒久的転送）を指定します。

### ティザーページに転送
サイト公開前にティザーページを用意して
外からはティザーページを
内からは製作中のページを表示させたい場合に使う。

```apache:.htaccess
# 2013年05月01日 09:00 まではティザーページを表示
RewriteCond %{TIME} <201305010900.*
# 指定したIPアドレスからは製作中のファイルが見られるように転送から除外
RewriteCond %{REMOTE_ADDR} !=XXX.XXX.XXX.1
# 指定IPが複数ある場合
RewriteCond %{REMOTE_ADDR} !=XXX.XXX.XXX.2
# 画像やスタイルまで転送してしまうとティザーページの画像がバツになるので除外
RewriteCond %{REQUEST_URI} !\.(css|jpe?g|png|js|gif|swf|ico)$
# ティザーページそのものも転送されちゃうとリダイレクトループになるので除外
RewriteCond %{REQUEST_FILENAME} !teaser\.html
# 一時的なリダイレクト
RewriteRule ^.*$ /teaser.html [R,L]
```

### 端末振り分け
ちょっと情報古いかもですが・・・。

```apache:.htaccess
# DoCoMo
RewriteCond %{HTTP_USER_AGENT} DoCoMo
RewriteRule ^(.*)$ /docomo/ [R]

# Softbank
RewriteCond %{HTTP_USER_AGENT} (J-PHONE|Vodafone|SoftBank)
RewriteRule ^(.*)$ /softbank/ [R]

# AU KDDI
RewriteCond %{HTTP_USER_AGENT} (KDDI|UP\.Browser)
RewriteRule ^(.*)$ /au/ [R]

# DDI Pocket
RewriteCond %{HTTP_USER_AGENT} DDIPOCKET
RewriteRule ^(.*)$ /ddi/ [R]

# WILLCOM
RewriteCond %{HTTP_USER_AGENT} WILLCOM
RewriteRule ^(.*)$ /willcom/ [R]

# iPod
RewriteCond %{HTTP_USER_AGENT} iPod
RewriteRule ^(.*)$ /ipod/ [R]

# iPhone
RewriteCond %{HTTP_USER_AGENT} iPhone
RewriteRule ^(.*)$ /iphone/ [R]

# iPad
RewriteCond %{HTTP_USER_AGENT} iPad
RewriteRule ^(.*)$ /ipad/ [R]

# Android
RewriteCond %{HTTP_USER_AGENT} Android
RewriteRule ^(.*)$ /android/ [R]

# Windows Mobile
RewriteCond %{HTTP_USER_AGENT} Windows\ Phone
RewriteRule ^(.*)$ /win_mobile/ [R]
```

### 存在しないファイルは全てアプリで処理する
wordpressなどCMSやフレームワーク等でよくあるやつですね。
存在するファイルは静的に表示し、存在しないファイルは全てアプリで処理させます。

```apache:.htaccess
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
```

### 条件が複雑になってきたらSetEnvIfを使うと良い
`RewriteCond` は `RewriteRule` 毎に書く必要があるので、
同じ条件を何度も書く必要がある場合は環境変数に入れるとよい。

複雑な条件の場合も環境変数に入れたほうが可読性が上がる。

```apache:.htaccess
SetEnvIf Request_URI "\.(gif|jpe?g|png)$" request_is=image
SetEnvIf Remote_Addr ^XXX.XXX.XXX.XXX$ access_from=self
SetEnvIf User-Agent "iPhone|iPod|iPad" smartphone=apple
SetEnvIf User-Agent "Android" smartphone=google
# 社外からスマホでアクセスした場合
RewriteCond %{ENV:request_is} !image
RewriteCond %{ENV:access_from} !self
RewriteCond %{ENV:smartphone} ^.+$
RewriteRule . /sp/ [R,L]
# 社内からは端末で振り分ける
RewriteCond %{ENV:request_is} !image
RewriteCond %{ENV:access_from} self
RewriteRule . /%{ENV:smartphone}/ [R,L]
```

### リダイレクトを書く上で注意すべきこと

* 日本語を記述するなら文字コードはUTF-8で。改行コードもLinuxなのでLFが良い。CRLFでも動くけどね。
* 記述ミスがあると設置したディレクトリ以下が全て500エラーになるので、そうなったときにリスクが大きいサイトでは十分注意してください。テスト環境でOKでも環境違うとNGという場合があるので、似た環境で行なうか、同環境の下層で事前にテストしたらいい。
* `RewriteCond` は `RewriteRule` 毎に必要。面倒でも毎回書く。
* `RewriteBase` は名前からして勘違いされがちですが `RewriteRule` の転送先がパスだった場合に付加されるベースパスです。書き換え前の条件や `RewriteCond` 条件には影響ありません。転送先がhttpから書かれている場合も影響ありません。