基于名称的虚拟服务器
Nginx 首先决定由哪个服务器来处理请求。下面有一个简单的配置,三个虚拟服务器都监听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 指令中使用默认的服务器参数:
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
参数
default_server
从0.8.21版本开始可用。在早期版本中,应该使用参数default
parameter 代替。
注意,默认的服务器是监听端口的属性,而不是服务器名的属性。稍后再详细介绍。
如何防止处理未定义服务器名的请求
如果不允许没有 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 地址和端口。然后,它根据与 IP 地址和端口匹配的服务器块的服务器名称条目测试请求的 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站点配置
现在让我们看看 Nginx 如何选择一个位置来处理一个典型的、简单的 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',FastCGl服务器执行该文件。变量$document_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