文章目录
- 1. 设置虚拟服务器
- 2. 配置locations
- 3. NGINX Location优先级
- 4. 使用变量
- 5. 返回特定状态码
- 6. 重写请求中的URI
- 7. 重写HTTP响应
- 8. 处理错误
- 参考文档
在较高的层次上,将NGINX配置为web服务器需要定义它处理哪些url以及如何处理这些url上的HTTP资源请求。在较低的级别上,NGINX配置定义了一组虚拟服务器,用于控制对特定域或IP地址的请求的处理。
每个HTTP虚拟服务器都定义了多个名为location的特殊配置实例,用于控制URI的处理。每个location都定义了当请求被映射到该location时的方案。每个location都可以代理请求或返回相应文件。此外,可以修改URI,以便将请求重定向到另一个location或虚拟服务器。此外,还可以返回特定的错误代码,并且可以根据每个错误代码配置特定页面。
1. 设置虚拟服务器
NGINX配置文件至少需要一个server指令,用于定义一个虚拟服务器。当NGINX处理请求时,它首先选择处理请求的虚拟服务器。
一个虚拟服务器由http上下文中的server指令来定义,例如:
http {
server {
# Server configuration
}
}
可以在http上下文中添加多个server指令来定义多个虚拟服务器。
server配置块通常包含一个listen指令,用于指定侦听请求的服务器IP地址和端口。接受IPv4和IPv6地址。IPv6地址需要括在方括号中。
下面的示例显示侦听IP地址127.0.0.1和端口8080的服务器配置:
server {
listen 127.0.0.1:8080;
# The rest of server configuration
}
如果省略端口,则使用标准端口。同样,如果省略地址,服务器将侦听所有地址。如果根本不包括listen指令,标准端口是80/tcp,这取决于超级用户权限。
如果有多个服务器与请求的IP地址和端口匹配,nginx将请求报文的host头部与server块的server_name指令进行比对。server_name参数可以是一个完整的名称,通配符或者正则表达式。通配符是一种字符串,可以在开始,结尾或两者包含星号(*)。星号匹配任何字符序列。nginx使用perl语法的正则表达式,在它们前面加上波形号(~)。示例列举了一个准确的名字:
server {
listen 80;
server_name example.org www.example.org;
#...
}
如果多个名称匹配请求的host报头,nginx将按以下顺序搜索名称并使用找到的第一个匹配项:
- 准确名称
- 以星号开头的最长通配符,如*.example.org
- 以星号结尾的最长通配符,如mail*
- 第一个匹配的正则表达式(按在配置文件中出现的顺序)
如果host头与任何服务器名称都不匹配,nginx将请求路由到请求到达端口的默认服务器。一般默认服务器是nginx.conf文件中列出的第一个,除非你使用listen指令的default_server参数明确指定一台服务器作为默认服务器。
server {
listen 80 default_server;
#...
}
2. 配置locations
NGNX可以基于请求URI向不同代理发送业务或提供不同的文件。这些块由server指令中的location指令定义。
例如,你能定义3个location块指导虚拟服务器将一部分请求发送到一台代理服务器,其他请求发送到另一台不同的代理服务器,通过本地文件系统提供文件来处理剩下的请求。
NGINX比较着请求的URI和所有location指令的参数,并应用匹配location中的指令。在每个location块,通常可以(除了少数例外)放置更多的location指令来进一步完善对特定请求组的处理。
location指令有两种类型的参数:前缀字符串(代表路径名)和正则表达式。要使请求URI与前缀字符串匹配,它必须以前缀字符串开头。
下面的location示例带有匹配请求URI的路径名参数,该示例以 /some/path/ 开始,例如 /some/path/document.html。
location /some/path/ {
#...
}
对于区分大小写的匹配,正则表达式前面是波形号 ~ ,对于不区分大小写的匹配,前面是波形号加星号 ~* 。下面的示例匹配在任何位置包含string.html或.htm的URI(正则表达式?表示匹配前面的字母 l 零次或一次):
location ~ \.html? {
#...
}
3. NGINX Location优先级
为了找到最匹配URI的location,NGINX首先将URI与location的前缀字符串对比。然后查找带正则表达式的location。
除非使用^~修饰符,否则正则表达式将具有更高的优先级。在前缀字符串中,NGINX选择最具体的那个(最长,最完整的字符串)。选择location的具体过程如下:
- 将接收到的URI与所有前缀字符串逐一匹配;
- = 意味着URI与前缀字符串完全匹配。如果出现完全匹配,停止继续搜索;
- 如果 ^~ 修饰符在最长的匹配前缀字符串前面,则不检查正则表达式;
- 存储最长的匹配前缀字符串;
- 将URI与正则表达式进行匹配;
- 中断第一个匹配的正则表达式并使用相应的location;
- 如果没有正则表达式匹配,使用与存储的前缀字符串对应的location。
= > ^~ >正则表达式 > 前缀字符串
= 修饰符的典型应用是用于 / 的请求。如果 / 的请求很频繁,在location指令中明确 =/ 的参数可以加速处理,因为匹配的搜索在第一次比较后就会停止。
location = / {
#...
}
location上下文可以包含如何处理请求的指令,这些指令类似:提供一个静态文件或者将请求发往代理服务器。在下面的示例中,匹配第一个location上下文的请求会接收到/data文件夹提供的文件,匹配第二个location的请求会被转发到 www.example.com 的代理服务器。
server {
location /images/ {
root /data;
}
location / {
proxy_pass http://www.example.com;
}
}
root指令提供了查找相关静态文件的系统路径。与该location关联的请求URI被附加到路径中,以获取要提供的静态文件的全名。在上面的示例中,针对请求 /images/example.png,nginx提供文件/data/images/example.png。
proxy_pass指令将请求传递到配置了URL访问的代理服务器。来自代理服务器的响应被传递给客户端。在上面的示例中,所有不以/images/开头的请求都被传递给了代理服务器。
4. 使用变量
你可以在配置文件中使用变量,通过定义环境,使nginx处理请求有所不同。变量在计算时被临时赋值,也被用作指令的参数。变量名称的开头用 \ 符号表示。变量根据NGINX的状态定义信息,例如当前正在处理的请求的属性。
有一些预定义的变量,例如$server_name这种核心HTTP变量。你可以使用set,map,geo指令来定义用户变量。大多数变量是在运行时计算的,并且包含与特定请求有关的信息。例如, $remote_addr包含客户端IP地址, $uri 包含当前URI值。
5. 返回特定状态码
某些网站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;
}
return指令可以同时包含在location和server上下文中。
6. 重写请求中的URI
通过使用rewrite指令,可以在请求处理期间多次修改请求URI。rewrite指令具有一个可选参数和两个必需参数。第一个必需的参数是匹配请求URI的正则表达式,第二个参数是用于替换的URI。可选的第三个参数是一个标志,它可以停止rewrite指令的进一步处理或者发送一个重定向(301或302码)。例如:
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
如上例所示,第二个参数users通过正则表达式获得。
你可以在server和location上下文中使用多个rewrite指令。NGINX会按指令出现顺序依次执行。当上下文被选中后,server上下文中的rewrite指令会被执行一次。
NGINX处理了一组重写指令后,它会按照新URI选择location上下文。如果选中的location包含rewrite指令,就依次执行。如果URI与任何一个都匹配,在所有已定义的rewrite指令被执行之后,将搜索新location。
以下示例显示了与return指令结合使用的rewrite指令:
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标志,随后的rewrite,return指令被忽略,但是NGINX继续处理不同URI的请求。类似的,URI /download/some/audio/file 被替换成 /download/some/mp3/file.ra。如果URI不满足任何一个rewrite指令,NGINX会向客户端返回403错误码。
有两个参数可以中断rewrite指令的进程:
- last 停止执行当前server或location上下文中的rewrite指令,但是NGINX查找匹配重写的URI的location,并应用新location中的rewrite指令。(意味着URI能够再次被改变)
- break 类似break指令,停止当前上下文中的rewrite指令进程,取消查找匹配新URI的location。新location中的rewrite指令不会被执行。
7. 重写HTTP响应
有时,您需要重写或更改HTTP响应中的内容,用一个字符串替换为另一个字符串。您可以使用sub_filter指令定义要应用的重写。该指令支持变量和替换链,从而使更复杂的更改成为可能。
例如,可以更改绝对链接,该链接引用代理以外的服务器:
location / {
sub_filter /blog/ /blog-staging/;
sub_filter_once off;
}
虚拟主机配置文件如下:
server {
listen 80;
root /www ;
location / {
sub_filter /blog/ /blog-staging/;
}
}
默认首页如下:
# cat /www/index.html
<html>
/blog/ <br>
/blog-staging/
</html>
浏览器访问结果:
另一个示例将 http:// 方法更改为 https:// 并将localhost地址替换为请求报文头的主机名。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也不会再次被修改了。
8. 处理错误
使用error_page指令,您可以配置NGINX以返回自定义页面以及错误代码,在响应中替换不同的错误代码,或者将浏览器重定向到其他URI。在以下示例中,error_page指令指定要返回的页面(/404.html),并附带404错误代码。
error_page 404 /404.html;
请注意,此指令并不意味着立即返回错误(return指令这样做),而只是指定错误发生时的处理方式。错误代码可能来自代理服务器,也可能是在NGINX处理期间发生的(例如,NGINX无法找到客户端请求的文件时返回404)。
在下面示例中,当NGINX找不到页面,它将代码404替换为301,并重定向客户端到http:/example.com/new/path.html。当客户端仍尝试使用其旧URI访问页面时,此配置很有用。301代码通知浏览器该页面已永久移动,并且在返回时自动用新地址替换旧地址。
location /old/path.html {
error_page 404 =301 http://example.com/new/path.html;
}
下面的配置示例表示当文件找不到时,将请求传递给backend。由于在error_page指令中的等号后没有指定状态码,因此对客户端的响应使用代理服务器返回的状态码(不一定是404)。
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指令告知NGINX,当文件找不到时,进行一次内部重定向。error_page指令最后参数中的 $uri 变量保存当前请求的URI,并将其传递给重定向。
例如,如果 /images/some/file 没有找到,就会被替换为 /fetch/images/some/file 并开始搜索相关location。最后,请求在第二个location上下文结束,并被代理到http://backend/。
如果文件找不到,open_file_cache_errors指令可以防止写入错误消息。这里没有必要这样做,因为丢失的文件已经被正确处理了。
参考文档
https://docs.nginx.com/nginx/admin-guide/web-server/web-server/