Nginx 常用功能

Nginx 四层访问控制

Nginx 中的访问控制功能基于 ngx_http_access_module 模块实现,可以通过匹配客户端源 IP 地址进行 限制

该模块是默认模块,在使用 apt/yum 安装的环境中默认存在,如果想要禁用,需要自行编译,然后显式 声明禁用该模块

deny address|CIDR|unix:|all; 	#拒绝访问的客户端,黑名单,可以是具体IP,网段,socket(1.5.1版本以上),所有

allow address|CIDR|unix:|all; 	#允许访问的客户端,白名单,可以是具体IP,网段,socket(1.5.1版本以上),所有
 		#deny 和 allow 指令同时存在时,按加载顺序生效 
 		#作用域 http, server, location, limit_except
 		
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       location = /a.html {
           allow 127.0.0.1; #a.html 只允许 127.1 访问,但实际上并不起作用,因为在server 和 location 中都没有deny
       } 					#所以还是所有人都可以访问
}
 		
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       location = /a.html { 
           deny all; 		#所有客户端都不能访问 a.html,但当前 server 中其它资源不受影响
           allow 127.0.0.1; #此处放行了127.1,但 deny 写在前面了,所以 127.1 也同样无法访问
       }	#要先写allow再写deny,即先写白名单再写黑名单
}
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       location = /a.html {
           allow 127.0.0.1; 		# 放行127.1
           deny 10.0.0.208; 		# 拒绝 10.0.0.208
           allow 10.0.0.0/24; 		# 放行 10.0.0.0/24 所有IP,但 10.0.0.208 在上一条被拒绝
           deny all; 				# 拒绝所有,兜底规则
       }
}

Nginx 账户认证

Nginx 中的账户认证功能由 ngx_http_auth_basic_module 模块提供,该模块也是默认模块

此种认证方式并不安全,如果服务端是 http 协议,而非 https 协议,则用户名和密码在网络中是明文传输的,可以被抓包工具截获

auth_basic string|off; #身份验证时对话框上的提示信息,新版浏览器几乎不支持,默认off,即不启用验证功能

auth_basic_user_file file; #指定身份认证的用户名和密码的文件路径,密码要使用 htpasswd 命令生成
		#作用域 http, server, location, limit_except
		

#安装密码工具
[root@ubuntu ~]# apt install apache2-utils -y
[root@rocky ~]# yum -y install httpd-tools

#创建用户名和密码
#首次使用需要使用 -c 选项指定文件路径
[root@ubuntu24 sites-enabled]# htpasswd -c /etc/nginx/conf.d/httpuser tom
New password:
Re-type new password:
Adding password for user tom

#新增用户,非交互式输入密码
[root@ubuntu24 sites-enabled]# htpasswd -b /etc/nginx/conf.d/httpuser jerry 123456
Adding password for user jerry

#查看文件,在生产环境中,基于安全考虑,可以将文件设为隐藏文件,修改属主属组,并配置读写权限
[root@ubuntu24 sites-enabled]# cat /etc/nginx/conf.d/httpuser
tom:$apr1$gLsiAeP6$O6vdhw2PojDu4CS0Bgf0r0
jerry:$apr1$vBE/0/2E$LsVy0VhXIq5riYDhoeEmA0

#再配置上添加验证
server{

  listen 80;
  server_name www.a30.com;
  root /var/www/html/www.a30.com;
  location = /a.html{
	auth_basic "pls input your name";		#访问 www.a30.com/a.html 时需要验证
	auth_basic_user_file conf.d/httpuser;	#同域名下其它资源不用验证
	}
}

自定义错误页面

在没有配置错误处理页面的情况下,非 200 状态码的响应请求返回的都是 Nginx 默认页面,我们可以通 过指令设置自定义的错误页面,不同的虚拟主机,不同的错误都可以设置成不同的错误页面

error_page code ... [=[response]] uri; #定义指定状态码的错误页面,可以多个状态码共用一个资源
 					#作用域 http, server, location, if in location
 					
 					
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
        
       error_page 400 404 502 503 504 error.html; #自定义指定状态码的错误页面
        
       location = /error.html {
               root /data/errors;
       }
}
[root@ubuntu ~]# ls /data/errors/
error.html

#通过重定向将错误页面重定向到其他页面
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       
       error_page 400 404 =302 /index.html; #通过302 重定向到 index.hmtl
}

server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       error_page 400 404 =302 http://www.baidu.com; #临时重定向
       error_page 402 503 =301 http://www.baidu.com; #永久重定向
}

定义错误日志

默认没有为每个 server 配置单独日志的情况下,所有错误日志和访问日志都是写在相同的文件中,我们 可以单独为每个 server 或 location 设置日志

#全局配置
[root@ubuntu24 sites-enabled]# cat /etc/nginx/nginx.conf | grep log
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;

error_log file [level]; #指定保存错误日志的文件和记录级别,错误级别可以查看之前日志服务管理的内容
 		#如果不需要记录日志,值可以写在 /dev/null
		#默认值 error_log logs/error.log error
		#作用域 main, http, mail, stream, server, location

[root@ubuntu24 sites-enabled]# cat www.a30
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
        
       error_log /var/log/nginx/www.a30.com.error.log; 	#为当前 server 配置定义单独的 error_log
       location = /abc { 										#此资源报错不记录日志
               error_log /dev/null;
       }
}

检测资源是否存在

try_files file ... uri; #按顺序查询资源是否存在,返回第一个匹配到的,如果没有匹配到,会内部重定向到最后一个资源

try_files file ... =code; #最后还可以加一个状态码

#默认虚拟主机中的 try_files
[root@ubuntu ~]# cat /etc/nginx/sites-enabled/default | grep try_files
 try_files $uri $uri/ =404;
 
[root@ubuntu24 sites-enabled]# cat www.a30
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       try_files $uri $uri.html $uri/index.html /index.html;
       location /a{
               try_files $uri $uri.html;
       }
       location /b{
               try_files $uri $uri.html =418;
       }
       error_log /var/log/nginx/www.a30.com.error.log;
}
# 测试
# http://www.a30.com/xyz 先找 xyz,往后依次是 xyz.html xyz/index.html /index.html
# http://www.a30.com/a 如果有 a 或 a.html 会匹配到,返回状态码是200,如果没有则返回 500错误页面
# http://www.a30.com/b 如果有 b 或 b.html 会匹配到,返回状态码是200,如果没有则返回 418错误页面

长连接配置

keepalive_timeout timeout [header_timeout]; 	#TCP握手建立连接后,会话可以保持多长时间,
 						#在此时间内,可以继续传送数据,而不用再次握手
						#默认值 keepalive_timeout 75s
						#header_timeout 用作响应头中显示,可以与前一个值不一样
                        #作用域 http, server, location
                        
keepalive_requests number; 	#一次请求不断开连接的情况下最多可以传送多少个资源
 					#默认值 keepalive_requests 1000;
					#作用域 http, server, location
					
#在请求过程中以上两项达到一项阀值,连接就会断开


server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       keepalive_timeout 15 30; 		#在当前server 中修改配置,服务端真实时长是15S,响应头中显示30S
}

[root@ubuntu24 sites-enabled]# curl www.a30.com -I
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 12 Sep 2024 09:02:26 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 31
Last-Modified: Thu, 12 Sep 2024 06:41:36 GMT
Connection: keep-alive
Keep-Alive: timeout=30		#此处显示 30,但实际只有15
ETag: "66e28d20-1f"
Accept-Ranges: bytes

作为下载服务器配置

Nginx 的 ngx_http_autoindex_module 模块可以将目录内容按指定格式生成目录内容列表,常用作配 置下载服务器

autoindex on|off; 				#是否显示目录内容列表,默认 off
autoindex_exact_size on|off; 	#是否以友好的方式显示文件大小,默认 on,表示显示文件具体字节数
autoindex_format html|xml|json|jsonp; 	#数据显示格式,默认 html
autoindex_localtime on|off 		#是否以本地时区显示文件时间属性,默认off,以UTC时区显示
					 #以上指令作用域均为 http, server, location
				
				
[root@ubuntu24 www.a30.com]# tree
.
├── 100M.img
├── a.html
└── test.html

1 directory, 3 files

#当前配置
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
}
#此时在浏览器中访问 http://www.a30.com,会返回403
#修改配置
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       autoindex on;
}
#在浏览器中访问显示出目录

作为上传服务器配置

client_max_body_size size; 		#设置允许客户端上传单个文件最大值,超过此值会响应403,默认1m

client_body_buffer_size size 	#用于接收每个客户端请求报文的body部分的缓冲区大小,默认16k,超过此大小时,
#数据将被缓存到由 client_body_temp_path 指令所指定的位置
 
client_body_temp_path path [level1 [level2 [level3]]]; 
#设定存储客户端请求报文的body部分的临时存储路径及子目录结构和数量
                                #子目录最多可以设三级,数字表示当前级别创建几个子目录,16进制
                                
                                
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       client_max_body_size 10m;
       client_body_buffer_size 1024k;
       client_body_temp_path /tmp/client_body_temp/ 1 2;
}

# client_body_temp_path /tmp/client_body_temp/ 1 2;
# 表示会在 /tmp/client_body_temp/ 创建 16个一级子目录 0-f, 256 个二级子目录,00-ff,这些目录在上传时才会创建

限流限速

限流限速背景

限速(rate limiting)是 Nginx 中一个非常有用但是经常被误解且误用的功能特性。我们可以用它来限 制在一段时间内的 HTTP 请求的数量,这些请求可以是如 GET 这样的简单请求又或者是用来填充登录表 单的 POST 请求

限速还可以用于安全防护用途,例如限制密码撞库暴力破解等操作的频率,也可以通过把请求频率限制 在一个正常范围来抵御 DDoS 攻击,更常见的使用情况是通过限制请求的数量来确保后端的 upstream 服务器不会在短时间内遭受到大量的流量访问从而导致服务异常

目前 Nginx 中主要的三种限速操作分别是:限制请求数(request),限制连接数(connection),限制响应速度(rate),对应在 Nginx 中的模块指令分别是 limit_reqlimit_connlimit_rate 三部份

Nginx 中限速(rate limiting)的主要算法原理就是基于在计算机网络中当带宽有限时十分常用的漏桶算 法,其基本原理是:以漏桶为例,水从顶部倒入,从底下漏出

  • 漏桶对应我们服务器的带宽或者是处理请求的能力或者是一个队列

  • 水表示客户端发送过来的请求

  • 倒入的水则代表客户端发送给服务器但尚未进行处理的请求,此时请求仍在队列(在桶内)

  • 漏出的水则代表从队列中出来即将发送给服务器端处理的请求,此时请求已经离开了队列(在桶外)

漏桶在一定程度上可以代表服务器的处理能力,请求根据先进先出(FIFO)调度算法等待处理,如果倒入水的速度小于漏水的速度,可以理解为服务器能够处理完所有的请求,此时整体服务表现正常。如果倒入水的速度大于漏水的速度,那么水桶内的水会不断增加直到最后溢出,这种情况下在水桶中的水可以理解为在队列中等待的请求,而溢出的水则表示直接被丢弃不处理的请求

限制单一连接下载速度
limit_rate rate; 		#对单个客户端连接限速,默认单位为字节,其它单位需要显式指定,表示每秒的下载速度
 						#限速只对单一连接而言,同一客户端两个连接,总速率为限速2倍,默认值0,表示不限制
 
limit_rate_after size; 	#在传输了多少数据之后开始限速,默认值0,表示一开始就限速
 
#作用域 http, server, location, if in location


server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       limit_rate 10k; 			#每秒下载速度为10K
       limit_rate_after 1m; 	#前1M不开启限速
}
限制客户端请求数

标记不同的客户端取决于我们在定义规则时的字段,取到相同的值,就可以认为是相同客户端,进而可 以根据此值进行限制

limit_req_zone key zone=name:size rate=rate [sync]; # 定义一个限速规则,供limit_req 指令调用
 		# key 定义用于限速的关键字,表示以什么为依据来限速
		# zone=name:size name 表示规则名称
		# size 表示使用多大内存空间存储 key 对应的内容,指桶大小
 		# 数据会在多个worker 进程共享
 		# 空间耗尽后会使用LRU算法淘汰旧的数据
 
		# rate=rate 限制请求速率,
		# 同一个key 每秒可以请求多少次或每分钟可以请求多少次
 		# [sync] 实现共享内存的区域同步,商业版支持
		# 作用域 http,定义好后需要在其它地方进行调用才生效
		
		
limit_req zone=name [burst=number] [nodelay|delay=number]
 
# zone=name 表示调用哪个 limit_req_zone
# [burst=number] 表示超过 rate 之后还能接收多少个请求,这些请求会被放到队列慢慢处理

# [nodelay|delay=number] 
# nodelay 表示 rate 匹配到的请求不会被放到队列而是直接处理,但后续请求返回 503
# delay=number 表示有多少个请求直接处理,剩下的加队列慢慢处理
# 作用域 http, server, location

limit_req_status code; 		# 因为 limit_req 配置被拒绝处理的请求的返回状态码,默认503, nginx 1.3.15 版本后可用
# 作用域 http, server, location

limit_req_log_level info|notice|warn|error
# 定义因 limit_req 配置被拒绝处理的请求的日志级别,默认error
# 作用域 http, server, location

limit_req_dry_run on|off; 	# on 表示 rate 参数无效,但共享内存中的数据还是有效,默认 off
# 作用域 http, server, location


#示例
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; #写在 http 中
server{				#$binary_remote_addr 表示客户端 IP 地址的二进制形式
       listen 80;
       server_name www.m60.com;
       root /var/www/html/www.m60.com;
       limit_req zone=mylimit; #调用
}
#在这个例子中,limit_req_zone 指令定义了一个名为mylimit的内存区域,用于存储客户端 IP 地址的二进制形式,存储空间为 10m
#同一客户端每秒能同时建立2个连接,2r/s 完整写法是 2requests/secends
#但是 nginx 是毫秒级别的控制粒度,2r/s 意味着对同一客户端在 500ms 只能处理一个请求
#会导致服务端在500ms 内只能处理一个请求,在同一个500ms 内第二个及以上请求会返回503

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; 
server{
       listen 80;
       server_name www.m60.com;
       root /var/www/html/www.m60.com;
        
       limit_req zone=mylimit burst=3
}
#这个例子中定义了客户端可以超过rate 速率的请求数,在当前配置中,如果500ms 内同一客户端有5个请求,则首先处理第1个
#后续第2个到第4个请求放到队列中,在随后的时间内,每隔500ms 处理一个
#第5个请求直接返回503

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; 
server{
       listen 80;
       server_name www.m60.com;
       root /var/www/html/www.m60.com;
        
       limit_req zone=mylimit burst=3 nodelay;
}
# burst=3 虽然使得客户端的请求变得 均匀平滑,但增加了响应时间,排在队列越后面的请求等待时间越久,如果请求数过多,可能会等到超时也不会被处理
# nodelay 表示无延时队列
# 当服务端在500ms 内收到同一客户端 5个请求的时候,第1个到第4个请求会被直接处理,同时标记队列中己占满,第5个返回503
# 后续每过500ms 释放出一个队列中的空间让新的请求进来
  • 不使用 nodelay:如果不设置 nodelay,当请求速率超过限制并且突发请求队列也满时,Nginx会将超出限制的请求放入队列中等待处理。这些请求会按照先进先出(FIFO)的原则排队,直到它们能够被处理。这可能会导致客户端在请求被处理之前经历较长的等待时间。

  • 使用 nodelay:当设置了 nodelay 后,Nginx会立即拒绝超出限制的请求,不会将它们放入队列中等待。这有助于减少客户端的等待时间,并可能防止由于请求堆积而导致的服务器资源耗尽。然而,这也意味着超出限制的请求将不会得到服务,这可能对某些应用程序的可用性产生影响

限制客户端并发连接数
limit_conn_zone key zone=name:size; 	# 定义一个限速规则,供 limit_req 指令调用
# key 定义用于限速的关键字,表示以什么为依据来限制并发连接数	$binary_remote_addr	用于表示客户端 IP 地址的二进制形式
# zone=name:size name 表示规则名称
# size 表示使用多大内存空间存储 key 对应的内容,指桶大小
# 数据会在多个worker 进程共享,空间耗尽后会使用LRU算法淘汰旧的数据
# 作用域 http

limit_zone name $variable size; # 在1.1.8版本后被弃用,改用 limit_conn_zone
limit_conn zone number; 		# zone 表示要调用的规则,number 表示要限制的连接数,不能写变量
# 作用域 http, server, location

limit_conn_dry_run on|off; 		# on 表示 limit_conn 不生效,默认 off
# 作用域 http, server, location

limit_conn_log_level info|notice|warn|error; 	# 因 limit_conn 被拒绝连接的日志的级别,默认 error
# 作用域 http, server, location

limit_conn_status code; # 因 limit_conn 被拒绝连接的返回状态码,默认503
# 作用域 http, server, location

Nginx 状态页

stub_status; #添加此指令后可开启 Nginx 状态页,作用域 server, location
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
       
       location /status{
       		stub_status;
       }
}

#在浏览器中访问http:// www.a30.com/status

Active connections: 2 
server accepts handled requests
 10 10 11 
Reading: 0 Writing: 1 Waiting: 1 

# Active connections   当前处于活动状态的客户端连接数,=reading+writing+waiting
# accepts 总数,自 Nginx 启动到当前己接收的客户端请求总数
# handled 总数,自 Nginx 启动到当前己处理完成的连接数,通常等于 accepts,如果有失败连接,则要去掉失败连接
# requests 总数,自 Nginx 启动到当前客户端己发送的请求总数
# Reading 状态,当前正在读取请求报文的连接数,值越大,说明排队现象严重,性能不足
# Writing 状态,正在向客户端发送响应报文过程中的连接数,值越大,说明访问量越大
# Waiting 状态,己建立连接,但没有数据传输的空闲连接数,开启 keep-alive,

Reading+Writing+Waiting=Active connections

Nginx 第三方模块的使用

第三方模块是对 Nginx 的功能扩展,需要在编译的时候用 --add-module=PATH 指定路径,所以在使用 前要先获得第三方模块的源码,当然,我们也可以自行编写第三方模块

相同的功能,如果Nginx 有官方模块实现,则尽量使用官方模块实现,如果官方没有该功能,我们才考 虑使用第三方模块,一般可以去 github 上搜索我们需要扩展模块

例如

https://github.com/openresty/echo-nginx-module 	# echo 模块,可以直接输出
https://github.com/vozlt/nginx-module-vts 		# 第三方流量监控模块

第三方模块需要使用编译版本,在编译安装时将模块加入到,所要安装的模块中去

[root@ubuntu24 nginx-1.26.2]# ./configure ...--add-module=/root/echo-nginx-module-master/ --add-module=/root/nginx-module-vts-master

Nginx 中的变量

Nginx 变量可以在配置文件中使用,用作判断或定义日志格式等场景,Nginx 变量可以分为内置变量和 自定义变量两种

Nginx 内置变量

Nginx 内置变量是 Nginx 自行定义的,可以直接调用

常用内置变量

$remote_addr # 客户端公网IP,如果经多层Nginx代理,那最后的Nginx 通过此变量无法获取客户端IP

$proxy_add_x_forwarded_for # 代理IP和真实客户端IP

$args # URL中的所有参数

$is_args # 是否有参数,有参数该变量值为 ?,没有参数值为空

$document_root # 当前资源的文件系统路径

$document_uri # 当前资源不包含参数的URI

$host # 请求头中的host值

$remote_port # 客户端随机问口

$remote_user # 经过 auth basic 验证过的用户名

$request_body_file # 作为反向代理发给后端服务器的本地资源名称

$request_method # 当前资源的请求方式 GET/PUT/DELETE 等

$request_filename # 当前资源在文件系统上的绝对路径

$request_uri # 不包含的主机名的URI,包含请求的资源和参数

$scheme # 请求协议, HTTP/HTTPS/FTP 等

$server_protocol # 客户端请求的协议版本 HTTP/1.0, HTTP/1.1, HTTP/2.0 等

$server_addr # 服务器IP

$server_name # 服务器主机名

$server_port # 服务器端口号

$http_user_agent # 客户端UA

$http_cookie # 客户端所有COOKIE

$cookie_<name> # 获取指定COOKIE

$http_<name> # 获取指定的请求头中的字段,如果字段有中划线要替换成下划线,大写转成小写

$sent_http_<name> # 获取指定的响应头中的字段,如果字段有中划线要替换成下划线,大写转成小写

$arg_<name> # 获取指定参数

用户自定义变量

在 Nginx 中,除了内置变量外,我们还可以使用 set 指令来自定义变量

set $variable value; # 自定义变量,变量名以$开头,变量值可以从其它变量中获取,也可以直接指定
 # 作用域 server, location, if
 
#例如
set $var1 1234; #直接赋值,数字
set $var2 "hello world"; #直接赋值,字符串,中间有空格
set $var3 $host; #间接赋值,从内置变量中获得值
set $var4 $var1; #间接赋值,从内置变量中获得值

自定义访问日志

访问日志是记录客户端访问服务器资源的记录,我们可以通过分析访问日志来统计当前网站的日请求 量,热点资源,热点时间段,平时响应时长,错误状态码占比,客户端IP分布,客户端所使用的浏览器 等信息,用好访问日志可以帮助网站所有者了解网站的具体运营情况,此日志作用重大

access_log path [format [buffer=size] [gzip[=level]] [flush=time] 
[if=condition]];
access_log off;

# path 日志路径
 # format 日志格式
 # buffer=size 定义 buffer 表示启用缓冲区,会异步落盘
 # gzip[=level] 启用gzip 压缩,此参数会自动启用buffer,默认缓冲区大小为64k,默认压缩级别为1
 # flush=time 强制落盘时间频率,在缓冲区满了,或者此参数规定的时间到了都会定磁盘
 # [if=condition] 条件判断,返回true 才会记日志
 # off 表示不启用日志
 # 默认值 access_log logs/access.log combined;
 # 作用域 http, server, location, if in location, limit_except
 
 
log_format name [escape=default|json|none] string ...;
 
 # name 日志格式名称,供 access_log 指令调用
 # [escape=default|json|none] 设置变量的字符转义,默认default
 # string ... 当前定义的日志格式要记录的具体内容
 # 默认值 log_format combined "...";
 # 作用域 http
 
#二进制包安装的nginx 默认 access_log 配置
[root@ubuntu ~]# cat /etc/nginx/nginx.conf | grep access_log
 access_log /var/log/nginx/access.log;
 
#默认 log_format 内容
log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
                    
                    
                    
#定义日志格式常用的变量

$remote_addr #客户端的IP地址
$remote_user #使用 HTTP 基本身份验证时的远程用户
$time_local #服务器本地时间
$request #客户端请求的 HTTP 方法、URI 和协议
$status #服务器响应的状态码
$body_bytes_sent #发送给客户端的字节数,不包括响应头的大小
$http_referer #客户端跳转前的来源页面
$http_user_agent #客户端的用户代理字符串
$http_x_forwarded_for #通过代理服务器传递的客户端真实 IP 地址
$host #请求的主机头字段
$server_name #服务器名称
$request_time #请求处理时间
$upstream_response_time #从上游服务器接收响应的时间
$upstream_status #上游服务器的响应状态码
$time_iso8601 #ISO 8601 格式的本地时间
$request_id #用于唯一标识请求的 ID
$ssl_protocol #使用的 SSL 协议
$ssl_cipher #使用的 SSL 加密算法


#示例
#自定义访问日志格式 - 字符串
log_format basic '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
                  
#自定义访问日志格式 - json 字符串   
log_format json_basic '{"remote_addr": "$remote_addr", '
                      '"remote_user": "$remote_user", '
                      '"time_local": "$time_local", '
                      '"request": "$request", '
					  '"status": "$status", '
                      '"body_bytes_sent": "$body_bytes_sent", '
                      '"http_referer": "$http_referer", '
                      '"http_user_agent": "$http_user_agent", '
					  '"http_x_forwarded_for": "$http_x_forwarded_for"}';

server{
 listen 80;
 server_name www.a30.com;
 root /var/www/html/www.a30.com;
 
 access_log /var/log/nginx/${host}_access.log basic;
 location /json{
 	access_log /var/log/nginx/${host}_json_access.log json_basic; #记录json 格式
 	return 200 "json";
 }
 
 location /test{ 
 	access_log off; #不记录
 	access log
 	return 200 "test";
 }
} 

Nginx 压缩功能

Nginx 中可以启用压缩功能,在服务端将要传输的的资源进行压缩后再发送给客户端,此设置可以有效 减小传送资源的大小,从而节约网络资源,但压缩会占用服务端的CPU资源

gzip on|off; #启用或禁用压缩功能,默认off,作用域 http, server, location, if in location

gzip_buffers number size; #Nginx在压缩时要向服务器申请的缓存空间个数和每个缓存大小,默认 32 4k 或 16 8k
	#作用域 http, server, location
	
gzip_comp_level level; #压缩比,默认 1,作用域 http, server, location

gzip_disable regex ...; #根据客户端请求头中的UA字段内容来确定在某些情况下禁用压缩,可以支持正则表达式
	#gzip_disable "MSIE [1-6]\."; 这种写法就表示 IE6 浏览器禁用压缩,默认为空
 	#作用域 http, server, location
 	
gzip_http_version 1.0|1.1; #启用gzip 压缩的最小版本,默认 1.1,即http/1.1 及更高版本才使用压缩
 	#作用域 http, server, location
 	
gzip_min_length length; #资源体积多大才启用压缩,默认20,作用域 http, server, location

gzip_proxied off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any ...;
 	#nginx作为反向代理时是否压缩后端返回数据,根据请求头中的Via 字段来判断
 	#默认值 off,不压缩
	#expired 如果请求头中包含 Expires,则压缩
	#no-cache 如果请求头中包含 Cache-Control:no-cache 则压缩
 	#no-store 如果请求头中包含 Cache-Control:no-store 则压缩
 	#private 如果请求头中包含 Cache-Control:private 则压缩
	#no_last_modified 如果请求头中不包含 Last-Modified 则压缩
 	#no_etag 如果请求头中不包含 ETag 则压缩
	#auth 如果请求头中包含 Authorization 则压缩
	#any 任何情况都压缩
	#作用域 http, server, location 
    
gzip_types mime-type ...; #指定要压缩的资源类型,默认 text/html,text/html 类型只要开启gzip 都会被压缩
 	# * 表示所有类型,作用域 http, server, location
 	
gzip_vary on|off; #是否在响应头中添加 Vary: Accept-Encoding,默认 off
 	#作用域 http, server, location 
    
    
#示例
#命令行工具默认不会发送压缩请求头,响应头中显示Content-Length: 612
[root@ubuntu24 ~]# curl -I 119.3.221.113
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 14 Sep 2024 08:24:26 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sat, 14 Sep 2024 07:14:48 GMT
Connection: keep-alive
ETag: "66e537e8-264"
Accept-Ranges: bytes

#显式指定压缩,响应头中能看到 Content-Encoding: gzip 内容,但看不到传输内容长度
#这是因为启用压缩后,传输的内容要进行压缩,大小会改变,但 header 又先于 body 传输,
#所以 header 在传输前并不知道 body 会被压成多大,所以无法给出body 大小
#如果又要压缩,又要返因 content-length,则需要 ngx_http_gzip_static_module 模块支持
#但可以在客户端统计,在浏览器中打开页面,通过开发者工具可以查看大小

[root@ubuntu24 ~]# curl curl -H "Accept-Encoding: gzip" -I 119.3.221.113
HTTP/1.1 200 OK
Date: Sat, 14 Sep 2024 08:25:59 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 14 Sep 2024 08:25:59 GMT
Content-Type: text/html
Last-Modified: Sat, 14 Sep 2024 07:14:48 GMT
Connection: keep-alive
ETag: W/"66e537e8-264"
Content-Encoding: gzip

favicon 图标配置

favicon.ico 文件是浏览器收藏网址时显示的图标,当客户端使用浏览器问页面时,浏览器会自己主动发 起请求获取页面的 favicon.ico文件,但是当浏览器请求的favicon.ico文件不存在时,服务器会记录404 日志,而且浏览器也会显示404报错

#解决办法 服务器不记录访问日志
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
        
       location = /favicon.ico {
               log_not_found off;
               access_log off;
       }
}

#解决办法 给出文件,并设置有效期
server{
       listen 80;
       server_name www.a30.com;
       root /var/www/html/www.a30.com;
        
       location = /favicon.ico {
               root /var/www/html/www.a30.com/static;
               expires 7d; #首次请求缓存后,7天内不再发起请求,但服务端更新后客户端有可能要7天后才更新
               access_log off;
       }
}

Nginx 实现 Https

Nginx 中的 Https 功能需要 ngx_http_ssl_module 模块支持,使用 Yum/apt 安装的 Nginx 中己经包含 了该模块的功能,如果使用的是自行通过源码编译安装的 Nginx,需要在编译的时候指定相关编译项

ssl on|off; #是否启用SSL,1.15版本中被弃用,1.25.1版本中被删除,后续不使用此参数 

ssl_buffer_size size; #Nginx在读取和写入SSL/TLS握手数据时使用的缓冲区大小,无关数据发送,默认值 16k
 	#作用域 http, server
 	
ssl_certificate file; #当前虚拟主机的证书文件,通常是PEM格式,
	#该文件中有两部份,分别是虚拟主机的证书和CA机构的证书,作用域http, server

ssl_certificate_key file; #当前虚拟主机的私钥文件路径,作用域 http, server

ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
 	#当前支持的SSL协议版本,默认值 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3
 	#作用域 http, server
 	
ssl_session_cache off|none|[builtin[:size]] [shared:name:size];
 	#配置SSL缓存,作用域 http, server
 	#off 禁用SSL/TLS会话缓存
	#none 通知客户端可以重用会话,但并没有缓存相关数据,默认值
	#builtin[:size] 使用OpenSSL内建缓存,可指定大小,每个worker 进程独享
 	#[shared:name:size] 使用共享缓存,每个worker进程共享该缓存中的数据,可指定name和大小
 
ssl_session_timeout time; #配置SSL/TLS会话缓存的超时时间,默认值 5m,作用域 http, server	
	#使用SSL/TLS会话缓存有助于减少服务器的加密和解密负担,提高HTTPS连接的响应速度,启用缓存需要
	#ssl_session_cache,ssl_session_timeout 两个选项一起使用	
	#SSL/TLS会话缓存存储的是SSL/TLS握手过程中生成的会话数据。在SSL/TLS握手过程中,服务器和客户端会交换一系列数据,其中包括协商的密钥、加密算法、会话标识符等信息。这些信息用于确保安全通信,并在建立连接后用于加密和解密通信的数据
	#SSL/TLS会话缓存中存储的主要数据包括 会话标识符(Session Identifier),主密钥(Master Secret),加密算法和参数
	#通过存储这些会话数据,SSL/TLS会话缓存允许服务器在处理新连接时,如果客户端提供了先前使用过的会话标识符,就可以重用这些数据,避免重新执行完整的SSL/TLS握手。这样可以大幅度减少握手过程中的计算和通信开销,提高性能和响应速度。同时,它还有助于减少服务器的负担,因为不需要重新生成新的密钥和协商参数
#安装软件
[root@ubuntu24 nginx]# apt install easy-rsa -y

[root@ubuntu24 ~]# cd /usr/share/easy-rsa/

#初始化证书目录
[root@ubuntu24 easy-rsa]# ./easyrsa init-pki

[root@ubuntu24 easy-rsa]# tree pki
pki
├── inline
├── openssl-easyrsa.cnf
├── private
└── reqs

4 directories, 1 file

#生成CA机构证书,不使用密码
[root@ubuntu24 easy-rsa]# ./easyrsa build-ca nopass
...
CA creation complete. Your new CA certificate is at:
* /usr/share/easy-rsa/pki/ca.crt

#生成私钥和证书申请文件
[root@ubuntu24 easy-rsa]# ./easyrsa gen-req www.a30.com nopass
...
Private-Key and Public-Certificate-Request files created.
Your files are:
* req: /usr/share/easy-rsa/pki/reqs/www.a30.com.req
* key: /usr/share/easy-rsa/pki/private/www.a30.com.key

#签发证书
[root@ubuntu24 easy-rsa]# ./easyrsa sign-req server www.a30.com
...
Certificate created at:
* /usr/share/easy-rsa/pki/issued/www.a30.com.crt

#合并服务器证书,签发机构证书为一个文件,注意顺序,先服务器证书,再CA证书
[root@ubuntu24 easy-rsa]# cat pki/issued/www.a30.com.crt  pki/ca.crt > pki/www.a30.com.pem

#给私钥加读权限
[root@ubuntu24 easy-rsa]# chmod +r pki/private/www.a30.com.key


#配置https
[root@ubuntu24 sites-enabled]# cat www.a30
server{
  listen 80;
  server_name www.a30.com;
  root /var/www/html/www.a30.com;
  keepalive_timeout 15 30;
  autoindex on;

server{
  listen 443 ssl;
  server_name www.a30.com;
  root /var/www/html/www.a30.com;
  autoindex on;

  ssl_certificate /usr/share/easy-rsa/pki/www.a30.com.pem;
  ssl_certificate_key /usr/share/easy-rsa/pki/private/www.a30.com.key;
  ssl_session_cache shared:sslcache:20m;
  ssl_session_timeout 10m;
}
-------------------------------------------
#配置http 强制跳转 https
server{
       listen 80;
       server_name www.a30.com;
       return 301 https://$host$request_uri; 	#301重定向
       rewrite ^(.*) https://$server_name$1 permanent; #rewrite 重定向,二选一
}
-----------------------------------------
#http 和 https 写在同一个配置中
server{
 listen 80;
 listen 443 ssl;
 server_name www.a30.com;
 root /var/www/html/www.a30.com;
 ssl_certificate /usr/share/easy-rsa/pki/www.a30.com.pem;
 ssl_certificate_key /usr/share/easy-rsa/pki/private/www.a30.com.key;
 ssl_session_cache shared:sslcache:20m;
 ssl_session_timeout 10m;
}
--------------------------------------

#同一个配置中自动跳转
server{
       listen 80;
       listen 443 ssl;
       server_name www.a30.com;
       root /var/www/html/www.www.a30.com;
       ssl_certificate /usr/share/easy-rsa/pki/www.a30.com.pem;
       ssl_certificate_key /usr/share/easy-rsa/pki/private/www.a30.com.key;
       ssl_session_cache shared:sslcache:20m;
       ssl_session_timeout 10m;
        if ($scheme = http){
               return 301 https://$host$request_uri;
               rewrite ^(.*) https://$server_name$1 permanent; #二选一
       }
}

Nginx 中配置防盗链

盗链是指某站点未经允许引用其它站点上的资源,基于访问安全考虑,Nginx 支持通过 ngx_http_referer_module 模块,检查和过滤 Referer 字段的值, 来达到防盗链的效果

HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉 服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如校验加载图片、文件 等来源是否是指定域名,如不是则禁止访问。因此HTTP Referer头信息是可以通过程序来伪装生成的, 所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况。

valid_referers none |blocked|server_names|string ...; 

#Nginx 会使用请求头中的 referer 字段值和 valid_referers 指定的规则进行对比,如果不匹配,会将 $invalid_referer 变量的值设为 1,默认该变量值为空字符串,作用域 server, location
# none 如果请求头中没有 referer 字段,则 $invalid_referer 变量值为空
# blocked 如果请求头中有 referer 字段,但其值不合法(不是以 http 或 https 开头),则$invalid_referer 变量为空
# server_names 具体主机名,可以写一个或多个,支持正则和通配符,如果请求头中的 referer 字段值与定义的 server_names 匹配,则$invalid_referer 变量为空
#Referer字段包含了发起请求的前一个URL地址,即用户访问当前页面之前所在的页面地址


server{
 listen 80;
 server_name www.a30.com;
 root /var/www/html/www.a30.com;
}
server{
 listen 80;
 server_name www.abc-123.com;
 root /var/www/html/www.abc-123.com;
}

[root@ubuntu ~]# cat /var/www/html/www.a30.com/test.html 
hello world
<img src="http://www.abc-123.com/test.jpg" />
#当访问者在浏览器中打开 http://www.a30.com/test.html 时,该页面会引用一个http://www.abc-123.com 站点的资源

#对于http://www.abc-123.com 站点而言,其资源就是被资链了

利用 valid_referers 指令实现防盗链

#对于 http://www.abc-123.com/test.jpg 而言,此次请求是从 http://www.a30.com 来的
#则只需要根据 referer 字段值禁用未经允许的访问即可

server{
       listen 80;
       server_name www.abc-123.com;
       root /var/www/html/www.abc-123.com;
       valid_referers none blocked server_names *.test.com ~\.baidu\. ~\.bing\. ~\.so\.;
        if ($invalid_referer){ 		# if 指令后面要有空格, 如果不是上述referer,就返回403
               return 403 "Forbidden Access";
       }
}
# valid_referers 指令定义了哪些HTTP Referer头部被认为是有效的  
    # none 表示直接访问(没有Referer头部)被认为是有效的  
    # blocked 表示Referer头部被浏览器或防火墙等设置为空值的情况也被认为是有效的  
    # server_names 表示从当前server_name中指定的域名过来的请求是有效的  
    # *.test.com 表示所有以.test.com结尾的域名过来的请求也是有效的  
    # ~\.baidu\. ~\.bing\. ~\.so\. 表示匹配以baidu.、bing.、so.开头的Referer头部也是有效的(这里使用了正则表达式,但注意正则表达式前的波浪线~可能因Nginx版本而异,通常不需要)

Nginx 中的 Rewrite

在 Nginx 中,rewrite 指令用于重写 URI,允许 Nginx 修改客户端请求的 URI,基于此,可用该指令实 现 URL 重定向,修改请求参数,改变请求含义,改变 URL 结构等,该指令来自于 ngx_http_rewrite_module 模块

ngx_http_rewrite_module 模块是 Nginx 中的一个核心模块,不管是 yum/apt 安装还是编译安装,默 认都己经包含在 Nginx 中了,它提供了强大的 URL 重写和重定向功能。主要作用是允许管理员通过配置 文件来修改客户端请求的 URI,从而实现重写 URL、重定向请求、更改请求参数等操作

相关指令说明

break; #中断当前相同作用域(location)中的其它 ngx_http_rewrite_module 模块的配置和指令,返回到上一作用域继续执行
 	#该指令后的其它指令和配置还会执行,只中断 ngx_http_rewrite_module 指令,作用域 server, location, if
 	
if (condition) { ... }# 允许在配置中使用条件判断,使用正则表达式(pcre风格)对变量进行匹配,匹配成功返回true,执行后续指令
 	# if指令仅能做单次判断,不支持 if else 多分支
 	# if ($var){ } 这种写法,如果变量对应的值是空字符串或0,就返回false
 	# nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
 	# 作用域 server, location
 # 支持的运算符
 # = 比较变量和字符串是否相等
 # != 比较变量和字符串是否不相等
 # ~ 区分大小写,是否匹配正则,包含
 # !~ 区分大小写,是否不匹配正则,包含
 # ~* 不区分大小写,是否匹配正则,包含
 # !~* 不区分大小写,是否不匹配正则,不包含
 # -f|!-f 判断文件是否存在|不存在 
 # -d|!-d 判断目录是否存在|不存在
 # -x|!-x 判断文件是否可执行|不可执行
 # -e|!-e 判断文件(包括文件,目录,软链接)是否存在|不存在 	
 
 
return code [text]; 
return code URL;
return URL; 	# 不写code ,默认值为302 
 # 直接向客户端返回状态码,字符串,或者URL,如果返回的字符串中包含空格,要加引号,如果返回URL,要写完整
 # 此指令后的其它指令或配置将不再执行,作用域 server, location, if
 
rewrite regex replacement [flag]; 
 # 通过正则表达式匹配来改变URI,在一个配置段中可以有一条或多条,按照顺序从上下往下匹配
 # 作用域 server, location, if
 # 如果有多条规则,被某一条规则命中并替换后,会用新的URI再从头开始逐一匹配,直到没有被命中为止,
 # 但是重复匹配次数不能超过 10次,否则会报500
 # regex PCRE 风格的正则表达式,表示要查找的内容
 # replacement 用于替换的字符串
 # [flag] 标志位,用于控制 rewrite 指令的行为
 
last|break|redirect|permanent
 #last   如果被当前 rewrite 规则匹配上,替换后结束本轮替换,开始下一轮替换
 # break   如果被当前 rewrite 规则匹配上,替换后结束当前代码段的重写替换,后续所有 rewrite 都不执行
 # redirect   如果被当前 rewrite 规则匹配上,替换后执行 302 临时重定向
 # permanent  如果被当前 rewrite 规则匹配上,替换后执行 301 永久重定向
 
# last 和 break 在服务器内部实现跳转,客户端浏览器地址栏中的信息不会发生变化
# redirect 和 permanent 在客户端实现跳转,客户端浏览器地址栏中的信息会发生变化

rewrite_log on|off; #是否记录 ngx_http_rewrite_module 模块产生的日志到 error_log 中,默认值 off
 #如果开启,需要将 error_log 的级别设为 notice,作用域 http, server, location, if
 
set $variable value; #设置变量,给变量赋值,作用域 server, location, if

last 和 break

相同点:

  • 无论是 break 还是 last,它们都会中止当前 location 块的处理,并跳出该块,客户端浏览器地址 栏中的信息不会发生变化

不同点:

  • break:终止当前代码段中的所有 rewrite 匹配

  • last:中止当前 location 中的 rewrite 匹配,用替换后的 RUI 继续从第一条规则开始执行下一轮 rewrite

PCRE 风格正则表达式

PCRE(Perl Compatible Regular Expressions)风格的正则表达式在设计上兼容Perl语言的正则表达式 语法,具有灵活且功能强大的特点。下面是一些 PCRE 风格正则表达式中常见的元字符和功能

#元字符

. #匹配除换行符外的任意字符
\w #匹配字母数字下划线中文字
\s #匹配任意空白字符
\d #匹配任意数字,相当于[0-9]
\b #匹配单词开始或结束
[] #匹配括号内的任意一个字符 [abc] 表示abc中的任意一个字符
[^] #匹配除了括号内字符之外的任意一个字符 [^abc] 表示任意一个除 abc 之外的字符

^ #匹配内容的开始位置
$ #匹配内容的结束位置
* #匹配前面的字符零次或多次
+ #匹配前面的字符一次或多次
? #匹配前面的字符零次或一次
{n} #匹配前面的字符n次
{n,} #匹配前面的字符至少n次
{n,m} #匹配前面的字符n次到m次
{,m} #匹配前面的字符最多m次

| #或,用于在模式中指定多个备选项
() #分组,用于将多个模式组合在一起,并捕获匹配的文本 $1 $2 $n 后向引用
\ #转义字符,用于取消元字符的特殊意义,或引入某些特殊字符
指令测试

break 指令测试

location /break{
        set $var1 baidu;
        echo $var1;
        break;
        set $var2 1234; 		# set 是属于 ngx_http_rewrite_module 模块指令,此句在 break 之后,不生效
        echo "$var1 -- $var2"; 	# 不输出 var2
       return 200 "hello break"; # return 是属于 ngx_http_rewrite_module 模块指令,此句在 break 之后,不生效
       
输出结果为
baidu
baidu --

if 指令测试

location /scheme{
 
 if ($scheme = http){   #$scheme 请求协议, HTTP/HTTPS/FTP 等
 return 200 "http";
 }
 if ($scheme = https){
 return 200 "https";
 }
 }
 location /test{
 return 200 $scheme;
 }
 
#测试
[root@ubuntu24 ~]# curl http://www.a30.com/scheme
http
[root@ubuntu24 ~]# curl -k https://www.a30.com/scheme
https

set 配合 if

set $slow 1;
       location =/test.img{        
       if ($slow){
            limit_rate 10k;
       }
  }
  
#测试
[root@ubuntu22:~]# wget http://www.a30.com/test.img
test.img              0%[                                                      ]  72.00K  11.5KB/s    eta 15m 24s
#成功限制

return 指令测试

#示例1
location /return{
        if ($http_user_agent ~* curl|wget|ApacheBench){		#$http_user_agent 客户端的用户代理字符串
           return 403 "agent error!";
       }
       return 200 "success";
   }
   
#测试
[root@ubuntu22:~]# curl -I http://www.a30.com/return
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 17 Sep 2024 05:48:10 GMT
Content-Type: application/octet-stream
Content-Length: 12
Connection: keep-alive
Keep-Alive: timeout=30

[root@ubuntu22:~]# curl http://www.a30.com/return
agent error!

[root@ubuntu22:~]# curl -A "chrome" http://www.a30.com/return
success

[root@ubuntu22:~]# curl -IA "chrome" http://www.a30.com/return
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 17 Sep 2024 05:49:10 GMT
Content-Type: application/octet-stream
Content-Length: 7
Connection: keep-alive
Keep-Alive: timeout=30


#示例2
location = /return_url{
               return http://www.baidu.com;
       }

#测试
[root@ubuntu22:~]# curl http://www.a30.com/return_url
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

[root@ubuntu22:~]# curl -IL http://www.a30.com/return_url
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Tue, 17 Sep 2024 05:52:02 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Keep-Alive: timeout=30
Location: http://www.baidu.com

HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Tue, 17 Sep 2024 05:52:02 GMT
Etag: "575e1f60-115"
Last-Modified: Mon, 13 Jun 2016 02:50:08 GMT
Pragma: no-cache
Server: bfe/1.0.8.18

rewirte 指令测试

location /{
               rewrite /1.html /2.html;
               rewrite /2.html /3.html;
       }
       location /2.html{
               rewrite /2.html /a.html;
       }
       location /3.html{
               rewrite /3.html /b.html;
       }
       
#测试
#如果访问1.html
# 1.html ----> 2.thml
# 2.html ----> 3.html
# 3.html ----> b.html
#最终访问的会是b.html

ewirte 指令测试 - 配合 break

location /{
               rewrite /1.html /2.html break;
               rewrite /2.html /3.html;
       }
       location /2.html{
               rewrite /2.html /a.html;
       }
       location /3.html{
               rewrite /3.html /b.html;
       }
       
#测试
#如果访问1.html
# 1.html ----> 2.thml   
# break 结束当前 server 配置段中的所有 rewrite
#最终访问的会是2.html

rewirte 指令测试 - 配合 last

location /{
               rewrite /1.html /2.html last;
               rewrite /2.html /3.html;
       }
       location /2.html{
               rewrite /2.html /a.html;
       }
       location /3.html{
               rewrite /3.html /b.html;
       }
       
#测试
#如果访问1.html
# 1.html ----> 2.thml last 结束当前 location 中的本轮 rewrite,继续执行下一轮rewrite
# 2.html ----> a.thml 一下轮 location /2.html 的优先级更高
#最终访问的会是a.html

rewirte 指令测试 - 配合 redirect

location /{
               rewrite /1.html /2.html redirect;
               rewrite /2.html /3.html;
       }
       location /2.html{
               rewrite /2.html /1.html;
       }
       
#测试
#如果访问1.html
# 1.html ----> 2.thml redirect 返回客户端让客户端去请求 2.html 
# 2.html ----> 1.thml 客户端请求 2.html 被 rewrite 1.html 
# 1.html ----> 2.thml redirect 返回客户端让客户端去请求 2.html 
# ... 无限循环

rewirte 指令测试 - 配合 permanent

location /{
               rewrite /1.html /2.html permanent;
               rewrite /2.html /3.html;
       }
       location /2.html{
               rewrite /2.html /a.html permanent;
       }
       location /3.html{
               rewrite /3.html /b.html;
       }

#测试
#如果访问1.html
# 1.html ----> 2.thml permanent 返回客户端让客户端去请求 2.html 
# 2.html ----> a.thml permanent 返回客户端让客户端去请求a.html
#最终访问的会是a.html
#除了状态码不一样之外,redirect 和 permanent 在流程上没有本质区别
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值