阅读之前,建议先阅读初识 Nginx。 之后,我们来了解一下 Nginx 配置。
处理哪些 URLS
和如何处理这些URLS
。具体来说,就是定义一些虚拟服务器(Virtual Servers),控制具有特定 IP 和域名的请求。location
s 来控制对 URIS
的选择。每一个 location
定义了对映射到自己的请求的处理场景:返回一个文件或者代理请求,或者根据不同的错误代码返回不同的错误页面。另外,根据 URI
的不同,请求也可以被重定向到其它 server
或者 location
设置虚拟服务器
listen:
server
http
上下文中的 server
http {
server {
# Server configuration
}
}
注意: http 中可以定义多个 server
server
配置块使用 listen
server {
listen 127.0.0.1:8080; # IPv4地址,8080端口
# listen [2001:3CA1:10F:1A:121B:0:0:10]:80; # IPv6地址,80端口
# listen [::]:80; # 听本机的所有IPv4与IPv6地址,80端口
# The rest of server configuration
}
上述配置,如果不写端口号,默认使用80端口,如果不写 IP ,则监听本机所有 IP。
server_name:
server
的 listen
IP 和端口号一模一样, Nginx 通过请求头中的 Host
与 server_name
server {
listen 80;
server_name lufficc.com www.lufficc.com;
...
}
server_name
- 完整的主机名,如:
api.lufficc.com
- 含有通配符(含有
*
- ),如:
*.lufficc.com
- 或
api.*
- 正则表达式,以
~
通配符只能在开头或结尾,而且只能与一个 . 相邻。www.*.example.org 和 w*.example.org均无效。 但是,可以使用正则表达式匹配这些名称,例如 ~^www\..+\.example\.org$ 和~^w.*\.example\.org$ 。 而且 * 可以匹配多个部分。 名称 * .example.org 不仅匹配www.example.org,还匹配www.sub.example.org。
对于正则表达式:Nginx 使用的正则表达式与 Perl 编程语言(PCRE)使用的正则表达式兼容。 要使用正则表达式,且必须以 ~
命名的正则表达式可以捕获变量,然后使用:
server {
server_name ~^(www\.)?(?<domain>.+)$;
location / {
root /sites/$domain;
}
}
()
之间匹配的内容,也可以在后面通过 $1
来引用,$2
表示的是前面第二个 ()
server {
server_name ~^(www\.)?(.+)$;
location / {
root /sites/$2;
}
}
server_name
server {
listen 80;
server_name api.lufficc.com *.lufficc.com;
...
}
Host
- 完整的主机名,如
api.lufficc.com
- 。
- 最长的,且以
*
- 开头的通配名,如:
*.lufficc.com
- 。
- 最长的,且以
*
- 结尾的通配名,如:
api.*
- 第一个匹配的正则表达式。(按照配置文件中的顺序)
api.lufficc.com
> *.lufficc.com
> api.*
Host
头部不匹配任何一个 server_name
,Nginx 将请求路由到默认虚拟服务器。默认虚拟服务器是指:nginx.conf
文件中第一个 server
或者 显式用 default_server
server {
listen 80 default_server;
...
}
location
URI 与 location
server
之后,Nginx 会根据 URI
s 选择合适的 location
location
- 前缀字符串(路径名称)
- 正则表达式
URI
s 必须严格的以它开头。例如对于 /some/path/
参数,可以匹配/some/path/document.html
,但是不匹配 /my-site/some/path
,因为 /my-site/some/path
不以/some/path/
location /some/path/ {
...
}
~
开头表示大小写敏感,以 ~*
开头表示大小写不敏感。注意路径中的 .
要写成 \.
。例如一个匹配以 .html
或者 .htm
结尾的 URI
的 location
:
location ~ \.html? {
...
}
^~
具体的搜索匹配流程如下:
- 将
URI
=
- 修饰符表明
URI
- 如果找到的最长前缀匹配字符串以
^~
- 存储匹配的最长前缀字符串。
- 测试对比
URI
- 找到第一个匹配的正则表达式后停止。
- 如果没有正则表达式匹配,使用 4 存储的前缀字符串对应的
location
- 。
=
修饰符拥有最高的优先级。如网站首页访问频繁,我们可以专门定义一个 location
来减少搜索匹配次数(因为搜索到 =
修饰的匹配的 location
location = / {
...
}
静态文件和代理
location
也定义了如何处理匹配的请求:返回静态文件 或者 交给代理服务器处理。下面的例子中,第一个 location
返回 /data
目录中的静态文件,第二个 location
则将请求传递给https://lufficc.com 域名的服务器处理:
server {
location /images/ {
root /data;
}
location / {
proxy_pass https://lufficc.com;
}
}
root
指令定义了静态文件的根目录,并且和 URI
拼接形成最终的本地文件路径。如请求/images/example.png
,则拼接后返回本地服务器文件 /data/images/example.png
proxy_pass
指令将请求传递到 URL 指向的代理服务器。让后将来自代理服务器的响应转发给客户端。 在上面的示例中,所有不以 /images /
开头的 URI
proxy_pass
设置为 https://www.baidu.com/
,那么访问 http://search.lufficc.com/ 将得到百度首页一样的响应(页面)(感兴趣的童鞋可以自己试一试搜索功能,和百度没差别呢):
server{
listen 80;
server_name search.lufficc.com;
location / {
proxy_pass https://www.baidu.com;
}
}
使用变量(Variables)
$
set
,map
和 geo
指令定义自定义变量。 大多数变量在运行时计算,并包含与特定请求相关的信息。 例如,$remote_addr
包含客户端 IP 地址,$uri
一些常用的变量如下:
变量名称 | 作用 |
|
|
|
|
| 主机名 |
| 请求中的参数值 |
|
|
| 代表客户端的请求地址 |
|
|
... | ... |
http
重定向到 https
server{
...
return 301 https://lufficc.com$request_uri;
...
}
返回特定状态码
return
location /wrong/url {
return 404;
}
return
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
return
指令可以包含在 location
和 server
server{
location / {
return 404;
}
}
或者:
server{
...
return 404;
location / {
...
}
}
错误处理
error_page
命令可以配置特定错误码的错误页面,或者重定向到其他的页面。下面的示例将在 404 错误发生时返回 /404.html
error_page 404 /404.html;
error_page
命令定义了如何处理错误,因此不会直接返回,而 return
http://example.com/new/path.html
。 此配置很有用,比如当客户端仍尝试用旧的 URI
location /old/path.html {
error_page 404 =301 http:/example.com/new/path.html;
}
URIs
rewrite
指令可以多次修改请求的 URI
。rewrite
的第一个参数是 URI
需要匹配的正则表达式,第二个参数是将要替换的 URI
。第三个参数可选,指示是否继续可以重写或者返回重定向代码(301或302)。例如:
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
server
和 location
上下文中包括多个 rewrite
指令。 Nginx
按照它们发生的顺序一个一个地执行指令。 当选择 server
时,server
中的 rewrite
Nginx
处理一组 rewrite
指令之后,它根据新的 URI
选择 location
。 如果所选 location
仍旧包含 rewrite
指令,它们将依次执行。 如果 URI
匹配所有,则在处理完所有定义的 rewrite
指令后,搜索新的 location
rewrite
指令与 return
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
/download/some/media/file
的 URI 被改为 /download/some/mp3/file.mp3
。 由于 last
标志,后续指令(第二个 rewrite
指令和 return
指令)被跳过,但 Nginx 继续以更改后的 URI 处理请求。 类似地,诸如 /download/some/audio/file
的 URI 被替换为/download/some/mp3/file.ra
。 如果 URI 不匹配 rewrite
last
与 break
的区别是:last
- : 在当前
server
- 或
location
- 上下文中停止执行
rewrite
- 指令,但是 Nginx 继续搜索与重写的URI匹配的
location
- ,并应用新
location
- 中的任何
rewrite
break
- :停止当前上下文中
rewrite
- 指令的处理,并取消搜索与新 URI 匹配的
location
- 。 不会执行新
location
- 中的
rewrite
附录
常用正则
.
?
+
*
- : 重复0次或更多次
\d
^
$
{n}
{n,}
[c]
[a-z]
- : 匹配a-z小写字母的任意一个
全局变量
$args
- : #这个变量等于请求行中的参数,同
$query_string
$content_length
$content_type
$document_root
$host
$http_user_agent
$http_cookie
$limit_rate
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$request_uri
- : 包含请求参数的原始URI,不包含主机名,如:
/foo/bar.php?arg=baz
- 。
$uri
- : 不带请求参数的当前URI,$uri不包含主机名,如
/foo/bar.html
- 。
$document_uri
http://localhost:88/test1/test2/test.php
$host
:localhost
$server_port
:88
$request_uri
:/test1/test2/test.php
$document_uri
:/test1/test2/test.php
$document_root
:/var/www/html
$request_filename
:/var/www/html/test1/test2/test.php