結論
- まず
server
とかlocation
を使おうとする try_files
など他の方法がないか考える- どうしてもどうしてもダメなら
map
とif
を使う
以上!
コツは「とにかく if
を使わない」ことです。
手続き的な書き方から宣言的な書き方に頭を切り替えるとうまく馴染めると思います。
例: wwwありでアクセスがきたらwwwなしに転送する
server {
listen 80;
listen 443;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
rewrite
要りません。
例: サブディレクトリごとに違うupstreamに流す
/wp/〜
は php-fpm
、 /redmine/〜
は unicorn
に流したい場合。
upstream fpm {
server 192.168.0.10;
}
upstream unicorn {
server 192.168.0.11;
}
location /wp/ {
proxy_pass http://fpm;
}
location /redmine/ {
proxy_pass http://unicorn;
}
rewrite
要りません。
例: ファイルがあれば表示、なければbackendに流す
try_files $uri $uri/ @backend;
rewrite
要りません。
try_filesに @〜
は1つしか書けないので、
複数書きたい場合は飛んだ先でまた try_files
して多段にしましょう。
例: 特定URLの接続元制限
/wp/〜
は 192.168.0.0/24、172.16.0.0/16からのみアクセス許可する場合
map $remote_addr $wpadmin {
default 0;
~*192\.168\.0\. 1;
~*172\.16\. 1;
}
location /wp/ {
if ($wpadmin = 0) {
return 403;
}
...
}
rewrite
要りません。
なお map
内の条件列挙では ~
や ~*
と条件分の間にスペースは要りません(あってはいけない)。
例: User-Agentごとの出し分け
upstream pc {
server ...;
}
upstream sp {
server ...;
}
upstream fp {
server ...;
}
...
map $http_user_agent $ua_type {
default "pc";
~*android "sp";
~*iphone "sp";
~*docomo "fp";
~*kddi "fp";
~*softbank "fp";
}
location / {
proxy_pass http://$ua_type;
...
}
つらみ。
デバッグのコツ
色々方法がありますが、個人的には変数とアクセスログを利用するのが簡単でお勧めです。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$trace"';
...
set $trace "";
location ~* \.(css|js|swf|jpeg|jpg|png|gif|ico) {
set $trace "$trace,location1";
}
location /maintenance/ {
set $trace "$trace,location2";
}
location / {
set $trace "$trace,location3";
rewrite .* /maintenance/;
}
このように設定して /
にアクセスすると
127.0.0.1 - - [29/Nov/2014:22:54:06 +0900] "GET / HTTP/1.0" 200 612 "-" "curl" "-" ",location3,location2"
みたいな感じで出力されます。
おまけ
......とまぁこんな話が書籍になってそのうちリリースされるかもしれません(可能性)