添加虚拟服务器
Nginx配置文件中至少包含一条定义虚拟服务器的server
指令。当Nginx处理一个请求时,第一个被选中的虚拟服务器将用于处理该请求。
虚拟服务器通过http
指令中的server
指令来定义,示例如下:
http {
server {
# 服务器配置
}
}
http
中可以包含多条server
指令来定义多个虚拟服务器。
通常server
指令中会包含一条listen
指令,用于指定该虚拟服务器将要监听的IP地址和端口
。示例如下:
server {
listen 127.0.0.1:8080;
# 其他配置
}
如果不填写端口,则采用标准端口。如果不填写ip地址,则监听所有地址。如果缺少整条listen指令,则标准端口是80/tcp
,默认端口是8000/tcp
,由超级用户的权限决定。
如果有多个server配置了相同的ip地址和端口,Nginx会匹配server_name
指令与请求头部的host
字段。server_name
指令的参数可以是精确的文本、通配符或正则表达式。通配符可以在字符串的头部、尾部或两端包含*
,*
可以匹配任意字符。Nginx采用Perl格式的正则表达式,以~
开头。以下是一个精确匹配的例子:
server {
listen 80;
server_name example.org www.example.org;
...
}
如果有多个server_name
匹配host
字段,Nginx根据以下规则选择第一个相匹配的server
处理请求:
- 精确匹配
- 以
*
开始的最长通配符,如*.example.org
- 以
*
结尾的最长通配符,如mail.*
- 第一个匹配的正则表达式(根据在配置文件中出现的先后顺序)
如果找不到任何与host
字段相匹配的server_name
,Nginx会根据请求端口将其发送给默认的server。默认server就是配置文件中第一个出现的server,也可以通过default_server
指定某个server为默认server,如下所示:
server {
listen 80 default_server;
...
}
配置Location指令
Nginx根据URL将请求发送给不同的代理,或处理不同的文件请求。由server
指令中的location
指令配置规则。
比如,可以为虚拟服务器配置三个location
指令,将一些请求发送给代理服务器#1,将另外一些请求发送给代理服务器#2,再由本地文件系统处理剩余请求。
Nginx会将请求的URL匹配所有的location
指令,请执行匹配location中的指令。每个location
指令中通常还会包含多条更为精细匹配的location
指令。
location
指令包含两类参数:前缀字符串
和正则表达式
。请求要匹配前缀字符串的话,必须以前缀字符串开始。
以下例子中location参数匹配以/some/path/
开始的请求URI,如/some/path/document.html
(不匹配/my-site/some/path
,因为/some/path
不在起始位置)。
location /some/path/ {
...
}
~
用于匹配区分大小写的正则表达式,~*
用于匹配不区分大小写的正则表达式。下面例子匹配任意包含.html
或.htm
的URI。
location ~ \.html? {
...
}
Nginx先匹配前缀字符串,然后再匹配正则表达式。正则表达式拥有较高优先级,除非使用^~
修饰符。在所有前缀字符串中,Nginx会挑选最精确的那个,也就是最长最匹配的那个。详细匹配过程如下:
- 匹配所有前缀字符串;
- 如果有一个
=
定义的精确匹配前缀字符串,停止继续匹配; - 如果
^~
在最长匹配的前缀字符串之前,将忽略正则表达式; - 存储最长的匹配前缀字符串;
- 匹配正则表达式;
- 找到第一个相匹配的正则表达,停止匹配过程,并执行该location指令;
- 如果没有正则表达式匹配,则使用第4部存储的最长前缀字符串;
=
修饰符的典型应用是匹配 /
请求。针对频繁访问/
的情况,将location
参数设置为= /
可以加速处理过程,因为整个匹配过程在第一条之后就结束了。
location = / {
...
}
location
指令内可以配置如何处理请求:处理静态文档或将请求转发给代理服务器。在下面的例子中,匹配第一个location
的请求可以访问/data
目录的文件,匹配第二个location
的请求将被转发到www.example.com
服务器。
server {
location /images/ {
root /data;
}
location / {
proxy_pass http://www.example.com;
}
}
其中root
指令指定了静态文件的文件系统路径,将与请求URI一起构成静态文件的完全路径。在上述例子中,请求/images/example.png
将返回服务器上位于/data/images/example.png
的文件。
proxy_pass
指令将请求转发到代理服务器,并将代理服务器的响应返回给客户端。在上述例子中,所有不是以/images/
开头的URI请求都将被转发到代理服务器。
使用变量
通过在配置文件中使用变量,可以让Nginx以不同的方式处理请求。变量的值在运行时计算获得,并可作为参数传递给指令。变量必须以$
开头。变量基于Nginx的状态定义信息,如正被处理请求的属性。
Nginx包含许多预设的变量,如core HTTP
变量集,也可以使用set
、map
和geo
指令来自定义变量。大多数变量都在运行时计算值,这些值一般都包含某个请求的相关信息。如$remote_addr
包含了IP地址,而uri
则包含了当前访问的URI
。
返回指定状态码
有些网站在处理错误或重定向时,会要求立即返回一个状态码。最简单的方式就是使用return
指令,如下所示:
location /wrong/url {
return 404;
}
return
指令的第一个参数是一个状态码。第二个是可选参数,可以是重定向的URL(当状态码是301、302、303和307时),也可以是返回的文本信息。示例如下:
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
location
和server
中都可以包含return
指令。
重写请求中的URI
在处理请求过程中,可以通过rewrite
指令重复修改请求的URI。rewrite
指令包含2个必填参数和1个可选参数。第一个参数是请求URI必须匹配的正则表达式。第二个参数是要替换的目标URI。第三个为可选参数,可以是一个是否继续执行后续rewrite
指令的标记,也可以发送一个重定向指令(状态码是301或302)。示例如下:
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
location
和server
中都可以包含多个rewrite
指令。Nginx从上到下依次磁性rewrite
指令,每次进入server
指令块时,rewrite
指令都会被执行一次。
Nginx执行完一系列rewrite
指令后,根据最新的URI来选择location
指令。如果location
中也包含rewrite
指令,它们也将被依次执行,执行完毕后将重新选择location
。
下面是一个rewrite
和return
联合一起使用的例子。
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
这个例子用于区分两套不同的URI。类似于/download/some/media/file
的URI将被改写为/download/some/mp3/file.mp3
。由于最后的标识last
,Nginx将忽略随后的两条指令,然后以新的URI继续处理请求。同样地,类似于/download/some/audio/file
的URI将被改写为/download/some/mp3/file.ra
。如果请求URI都不匹配上述两条rewrite
指令,Nginx将返回403错误代码。
rewrite
指令可以包含以下两种参数,用于中断处理过程:
- last - 停止执行当前
server
或location
中的rewrite
指令,并以新的URI查找新的location; - break - 停止执行当前上下文环境内的
rewrite
指令,并不以新的URI查找新的location;
重写HTTP返回信息
sub_filter
指令支持重写或修改HTTP请求的响应内容,如替换某个字符串。该指令支持变量和链式替换。
下例中,将指向服务器的链接改为指向代理服务器的链接:
location / {
sub_filter /blog/ /blog-staging/;
sub_filter_once off;
}
另一个例子是将http请求改为https请求,并将请求头部的本地主机地址改为主机名。sub_filter_once
指令用于告诉Nginx是否连续执行location
中的sub_filter
指令。
location / {
sub_filter 'href="http://127.0.0.1:8080/' 'href="https://$host/';
sub_filter 'img src="http://127.0.0.1:8080/' 'img src="https://$host/';
sub_filter_once on;
}
注意:被sub_filter
指令修改后的内容将不会再被其他sub_filter
指令修改。
错误处理
error_page
指令用于返回一个自定义错误页面和一个错误代码、修改响应中的错误代码或重定向到不同的URI。在下面的例子中,error_page
指令返回404错误和一个错误页:
error_page 404 /404.html;
注意:该指令并不会马上返回(这是return
指令做的事),仅仅指定出错时如何处理。错误代码可以能来自于代理服务器,也可能来自Nginx本身(如Nginx没有找到请求的文件)。
在下面的例子中,当Nginx未能找到请求的页面时,不会返回404,而会返回303和一个重定向到新页面指令。这通常用于处理客户端访问旧地址的情况。
location /old/path.html {
error_page 404 =301 http:/example.com/new/path.html;
}
以下例子中,当访问一个不存在的文件时,Nginx会将请求重定向到http://backend
。由于error_page
指令未指定重定向代码,该代码将由重定向后的http://backend
返回。
server {
...
location /images/ {
# Set the root directory to search for the file
root /data/www;
# Disable logging of errors related to file existence
open_file_cache_errors off;
# Make an internal redirect if the file is not found
error_page 404 = /fetch$uri;
}
location /fetch/ {
proxy_pass http://backend/;
}
}
在上述例子中,当请求文件未找到时,error_page
指令将发起一个内部重定向。$url变量持有当前请求的URI,并被传递给重定向。
假设请求的/images/some/file
文件未找到,将被重定向到/fetch/images/some/file
,同时搜索新的location
。最终,请求将被第二个location
处理,并被代理到http://backend
。
open_file_cache_errors
指令可用于未找到请求文件时,禁止产生错误消息。在上述例子中可以忽略,因为错误已被正确处理。