nginxで名前ベースのバーチャルホストの複数指定をするときの注意点

先日、wikipedia:冒険遊び場 に参加してきて、森の中を駆けずり回ったり、泥んこ遊びをしたり、たき火でおにぎりや焼きイモを焼いたりましまろを炙ったりして食べたhirose31です。あといまだにnginxかngnixかつづりがおぼえられないhirose31です。

nginx (0.6系) で、ひとつのserverブロックで複数の名前ベースのバーチャルホストを設定するには、server_nameディレクティブをこんな感じで指定します:

  1. 列挙する: chikin.curry.example.com beef.curry.example.com pork.curry.example.com
  2. 先頭(か末尾)にワイルドカード: *.curry.example.com
  3. 正規表現

ここで注意しなければならないのは、nginxがLocationヘッダのリダイレクトをする場合です。例えば、http://example.com/dirname のようにパスがディレクトリなのに末尾のスラッシュがないリクエストが来た場合のレスポンスがこれにあたります。

デフォルトでは、nginxがLocationヘッダで使うホスト名はserver_nameディレクティブで最初に指定されている文字列です。

例えば、こんな感じで設定している場合、

http {
  ...
  server {
    listen       4649;
    server_name  ~^(chikin|be+f|pork)\.curry;

リダイレクトがかかるようなHTTPリクエストをすると、レスポンスはこんな感じなってしまいます。

goa[~]$ curl -i http://beeeeeeeeeeeef.curry.example.com/tabetai
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Mon, 20 Apr 2009 09:23:46 GMT
Content-Type: text/html
Content-Length: 178
Location: http://~^(chikin|be+f|pork)\.curry/tabetai/
Connection: keep-alive

<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>

Locationヘッダのホスト名がこれではまずいですね^^

というのにさっき気がついたので、

server_name_in_redirect  off;

にしました。

offにすると、server_nameディレクティブじゃなくて、クライアントがリクエストしてきたHostヘッダの文字列がLocationのホスト名として使われるようなります。

server_name_in_redirectはserverブロックはもちろん、httpブロックにも書けるので、httpブロックでoff指定して全serverブロックで有効になるようにしました。