nginxによるリクエスト処理
| 未定義のサーバー名を持つリクエストの処理を防止する方法 名前ベースとIPベースの仮想サーバーの混合 シンプルなPHPサイトの設定 |
名前ベースの仮想サーバー
nginxはまず、リクエストを処理するサーバーを決定します。3つの仮想サーバーがすべてポート*:80でリスンするシンプルな設定から始めましょう。
server {
listen 80;
server_name example.org www.example.org;
...
}
server {
listen 80;
server_name example.net www.example.net;
...
}
server {
listen 80;
server_name example.com www.example.com;
...
}
この設定では、nginxはリクエストのヘッダーフィールド「Host」のみをテストして、リクエストをどのサーバーにルーティングするかを決定します。その値がサーバー名と一致しない場合、またはリクエストにこのヘッダーフィールドが含まれていない場合、nginxはリクエストをこのポートのデフォルトサーバーにルーティングします。上記の設定では、デフォルトサーバーは最初のサーバーです。これはnginxの標準的なデフォルト動作です。listenディレクティブのdefault_serverパラメーターを使用して、明示的にデフォルトサーバーを設定することもできます。
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
default_serverパラメーターはバージョン0.8.21から利用可能です。それ以前のバージョンでは、代わりにdefaultパラメーターを使用する必要があります。
デフォルトサーバーは、サーバー名ではなく、リスンポートのプロパティであることに注意してください。これについては後で詳しく説明します。
未定義のサーバー名を持つリクエストの処理を防止する方法
「Host」ヘッダーフィールドのないリクエストを許可しない場合は、リクエストをただドロップするサーバーを定義できます。
server {
listen 80;
server_name "";
return 444;
}
ここでは、サーバー名が空文字列に設定されており、「Host」ヘッダーフィールドのないリクエストと一致します。そして、接続を閉じるnginx独自の非標準コード444が返されます。
バージョン0.8.48以降、これはサーバー名のデフォルト設定であるため、server_name ""は省略できます。それ以前のバージョンでは、マシンのホスト名がデフォルトのサーバー名として使用されていました。
名前ベースとIPベースの仮想サーバーの混合
いくつかの仮想サーバーが異なるアドレスでリスンする、より複雑な設定を見てみましょう。
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
...
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
...
}
この設定では、nginxはまず、リクエストのIPアドレスとポートを、serverブロックのlistenディレクティブと照合します。次に、IPアドレスとポートに一致したserverブロックのserver_nameエントリに対して、リクエストの「Host」ヘッダーフィールドをテストします。サーバー名が検出されない場合、リクエストはデフォルトサーバーによって処理されます。たとえば、192.168.1.1:80ポートで受信されたwww.example.comのリクエストは、192.168.1.1:80ポートのデフォルトサーバー、つまり最初のサーバーによって処理されます(このポートにはwww.example.comが定義されていないため)。
既に述べたように、デフォルトサーバーはリスンポートのプロパティであり、異なるポートに対して異なるデフォルトサーバーを定義できます。
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
server {
listen 192.168.1.1:80 default_server;
server_name example.net www.example.net;
...
}
server {
listen 192.168.1.2:80 default_server;
server_name example.com www.example.com;
...
}
シンプルなPHPサイトの設定
次に、典型的なシンプルなPHPサイトのリクエストの処理方法を見てみましょう。
server {
listen 80;
server_name example.org www.example.org;
root /data/www;
location / {
index index.html index.php;
}
location ~* \.(gif|jpg|png)$ {
expires 30d;
}
location ~ \.php$ {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}
nginxはまず、リストされている順序に関係なく、リテラル文字列によって与えられる最も具体的なプレフィックスロケーションを検索します。上記の設定では、唯一のプレフィックスロケーションは「/」であり、任意のリクエストと一致するため、最後の手段として使用されます。次に、nginxは設定ファイルにリストされている順序で、正規表現によって与えられるロケーションをチェックします。最初に一致する正規表現で検索は停止し、nginxはこのロケーションを使用します。正規表現がリクエストと一致しない場合、nginxは先に検出された最も具体的なプレフィックスロケーションを使用します。
すべてのタイプのロケーションは、引数なしでリクエストラインのURI部分のみをテストすることに注意してください。クエリ文字列の引数は、次のようにいくつかの方法で指定できるためです。
/index.php?user=john&page=1 /index.php?page=1&user=john
また、誰でもクエリ文字列に何でも要求できます。
/index.php?page=1&something+else&user=john
次に、上記の設定でリクエストがどのように処理されるかを見てみましょう。
- 「
/logo.gif」というリクエストは、最初にプレフィックスロケーション「/」と一致し、次に正規表現「\.(gif|jpg|png)$」と一致します。したがって、後者のロケーションによって処理されます。「root /data/www」ディレクティブを使用して、リクエストはファイル/data/www/logo.gifにマッピングされ、ファイルがクライアントに送信されます。 - 「
/index.php」というリクエストも、最初にプレフィックスロケーション「/」と一致し、次に正規表現「\.(php)$」と一致します。したがって、後者のロケーションによって処理され、リクエストはlocalhost:9000でリスンしているFastCGIサーバーに渡されます。fastcgi_paramディレクティブは、FastCGIパラメーターSCRIPT_FILENAMEを「/data/www/index.php」に設定し、FastCGIサーバーはファイルを実行します。変数$document_rootはrootディレクティブの値と等しく、変数$fastcgi_script_nameはリクエストURI(つまり「/index.php」)と等しくなります。 - 「
/about.html」というリクエストは、プレフィックスロケーション「/」のみに一致します。したがって、このロケーションで処理されます。「root /data/www」ディレクティブを使用して、リクエストはファイル/data/www/about.htmlにマッピングされ、ファイルがクライアントに送信されます。 - 「
/」というリクエストの処理はより複雑です。プレフィックスロケーション「/」のみに一致します。したがって、このロケーションで処理されます。次に、indexディレクティブは、そのパラメーターと「root /data/www」ディレクティブに従って、インデックスファイルの存在をテストします。ファイル/data/www/index.htmlが存在せず、ファイル/data/www/index.phpが存在する場合、ディレクティブは「/index.php」への内部リダイレクトを行い、nginxはクライアントからリクエストが送信されたかのように、再度ロケーションを検索します。前述のように、リダイレクトされたリクエストは最終的にFastCGIサーバーによって処理されます。
| 執筆者:Igor Sysoev 編集者:Brian Mercer |