nginx-相关功能分析 第四章

时间:2024-10-06 11:34:44

# Nginx服务器的rewrite、全局变量、重定向和防盗链相关功能

一:Nginx 后端服务器组的配置:

1、upstream: 用于定义可由proxy_pass,fastcgi_pass,uwsgi_pass,scgi_pass,memcached_pass和grpc_pass指令引用的服务器组。

upstream backend {              #   upstream 定义后端服务组名称
server backend1.example.com weight=; #server 定义服务地址和端口 ,端口默认 80
server backend2.example.com:8080 max_fails=3 fail_timeout=30s ;   #定义在30s 中,这个节点负载失败3次 就标记节点down        
server unix:/tmp/backend3; server backup1.example.com: backup;
server backup2.example.com: backup;
} server {                  #定义对外发布业务的接口及调用的服务组
location / {
proxy_pass http://backend;
}
}

2、nginx 的 upstream支持的集中调度算法:

nginx-相关功能分析  第四章
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动删除。
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session 保持的问题。
4、fair(第三方)
可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配,Nginx本身默认是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
5、url_hash(第三方)
  按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率,Nginx本身默认是不支持url_hash的,如果需要这种高度算法,必须安装Nginx的hash软件包。
6、least_conn
  根据后端服务器的连接状况进行分配客户请求,连接最少的服务器将被有限分配客户端请求。
nginx-相关功能分析  第四章

二:Nginx服务器的rewrite功能介绍:

Nginx服务器利用ngx_http_rewrite_module 模块解析和处理rewrite请求,所以说此功能依靠 PCRE(perl compatible regularexpression),因此编译之前要安装PCRE库,rewrite功能时nginx服务器的基本功能之一,用于实现URL的重写,URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问,另外还可以在一定程度上提高网站的安全性。

1、地址重写与地址转发:

地址重写 (rewrite )和地址(redirect) 转发是两个不同的概念,:

  rewrite 表示服务器和代理服务器从客户端读取访问的URL ,更改URL (host or uri) 做rewrite 操作。然后根据rewrite 后的访问路径去获取资源然后响应给客户端,此时客户端看到的url 不变,但实际获取资源的路径发生了变化。 

  redirect 表示服务器或者代理服务器从客户端获取访问的URL,根据定制的策略响应给客户端 301/302 ,然后客户端根据重新获取的访问路径去获取资源,此时浏览器的的URL 发生了变化。

   #301是永久重定向,而302是临时重定向

 2、if指令:

2.1:用于条件判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,用法如下:

if ($变量) { 
  action
}

注: 如果$变量的值为空字符串或是以0开头的任意字符串,则if指令认为该条件为false,其他条件为true。

2.2:使用“=”(等于)和“!=”(不等于)比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false。

if ($request_method = POST) {
return 405;
} #条件里的字符串不需要加引号

2.3:使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接:

双目测试:运算所需变量为两个的运算符叫做双目运算符,如下几个运算符:

~: #表示在匹配过程中区分大小写字符,(可以通过正则表达式匹配),满足匹配条件为真,不满足为假。
~*: #表示在匹配过程中不区分大小写字符,(可以通过正则表达式匹配),满足匹配条件为真,不满足问假。
!~:#区分大小写不匹配,不满足为真,满足为假,不满足为真。
!~*:#为不区分大小写不匹配,满足为假,不满足为真。

^~ :#如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。

注意:使用~和~!在匹配成功时if指令认为条件为true,匹配失败为false,使用!~和!~*匹配失败时if指令认为条件为true,否则为false,在正则表达式中,可以使用小括号对变量进行截取,在大括号中使用$!...$9引用截取的值,如下:

nginx-相关功能分析  第四章
if ($http_user_agent ~ MSIE) {  #if语句尽量用在location当中,尽量不要在http或server中使用,会出现莫名的错误。
#判断客户端的浏览器中是否含有MSIE的字符串,如果包含则为true
} #########################################
if ($http_cookie ~* "id="([^;]+)(?:;)") {
#Nginx配置,可以使用$!和$2获取截取到的值,如:
# set $id $1; 将截取到的id的值赋值给$id变量以备后用
}
注意:整个正则表达式一般不需要加引号,但是如果含有右大括号"}"或者分分号";"的时候,就必须要给整个正则表达式加上引号""
nginx-相关功能分析  第四章

3、文件和目录测试:单目测试,判断文件或者目录是否存在

3.1 -f和! -f:判断请求的文件是否存在和是否不存在

nginx-相关功能分析  第四章
-f 表示如果请求的文件存在,则if指令为true,如果请求的文件不存在,则if指令为false。使用! -f的时候,如果请求的文件不存在但是目录存在,if指令认为条件为true,如果请求的文件和目录都不存在,则if指令认为条件为false,如果请求的文件存在,也为false,如下:
if (-f $request_filename) {
#判断请求的文件是否存在
} if (! -f $request_filename) {
#判断请求的文件是否不存在
}
nginx-相关功能分析  第四章

3.2 -d和! -d: #判断请求的目录是否存在和是否不存在。

使用-d时,如果请求的目录存在,则if指令认为条件为true,如果请求的目录不存在,则认为条件为false,当使用! -d的时候,如果请求的目录不存在但是目录的上级存在,if指令认为条件为true,如果该目录和他的上级都不存在,则为false,如果请求的目录存在也未false,和of和! -f基本一致。

3.3 -e和! -e: #判断请求的文件或目录是否存在和是否不存在。

判断文件或目录是否存在,相当于-f和-d的功能合体,当使用-e时,如果请求的文件或目录存在则if指令认为条件为true,否则为false,当使用! -e时,如果请求的文件或目录以及该文件的上级都不存在,则为false,否则为true。

3.4 -x和 ! -x: #判断文件是否可执行和是否不可执行。

使用-x如果文件可执行则返回true,否则为fasle,使用! -x的时候如果文件不可执行返回true,否则为false。

4、break指令:用于中断当前相同作用域中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的指令配置就不再生效了,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和location块以及if块中使用,使用语法如下:

location /test {
root html;
index index.html index.htm;  
     break; #return之后的将不再执行,之前的可以执行
      }

 5、return指令:用于完成对请求的处理,并直接向客户端返回响应状态码,处于此指令后的所有配置都将不被执行,return可以在server、if和location块进行配置,用法如下:

return (text); #返回给客户端的响应体内容,可以调用变量
return code; #返回给客户端HTTP状态码,范围为0-999
return URL; #返回给客户端的URL地址

注意:从nginx 0.8.42开始,当code使用301时表示永久重定向,302为临时重定向。303表示当前的响应可以在另一个URL找到,307表示请求的资源临时从不同的URL响应

6、rewrite指令:通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配。

nginx-相关功能分析  第四章
URI(universal resource identifier):通用资源标识符,用于对网络中各种资源进行标示,有存放资源的主机名、片段标识符和相对URL三部分组成,存放资源的主机名一把由传输协议(scheme)、主机和资源路径三部分组成,片段标识符执行资源内容的具体元素,相对URL标示主机上的相对路径,一般格式为:scheme:[//] [[用户名[:密码]@]主机名:[端口号]][/资源路径名],如http://www.a.com:8080/path/file/index.html,Nginx就是对其中的URI /path/file这部分进行处理和匹配,但是不能处理http://www.a.com,因为Nginx接受到的URL不包含http://www.a.com。
URL(uniform resource location):统一资源定位符,是用于在Internet中描述资源的字符串,是URL的子集,主要包括传世协议(scheme)、主机(IP、端口号或者域名)和资源具体地址(目录和文件名)等三部分,一般格式为 scheme://主机名[:端口号][/资源路径],如:http://www.a.com:8080/path/file/index.html就是一个URL路径
URI就是一种资源定位机制,它是比较笼统地定位了资源,并不局限于客户端和服务器,而URL就定位了网上的一切资源,只要是网上的资源,都有唯一的URL。
nginx-相关功能分析  第四章

注:rewrite指令接收到的URI为 /path/file,不包含参数,如/path/file/arg1=value1&argv2=value2,只会接收到/path/file,不包含arg1=value1&argv2=value2,但是我们可以使用nginx内置的全局变量$request_uri来匹配用户的uri,在$request_uri后面要添加问号,replacement支持nginx全局变量的使用,常用的还要$uri和$args等,如:

rewrite www.a.com  http://www.b.com$request_uri? permanent;

注意:replacement是匹配成功后用于替换URL中被截取内容的字符串,默认情况下,如果该字符串是有http://或者https://开头的,则不会继续向下进行其他处理,而且直接将重写后的URL返回给客户端。

7、flag:用来设置rewrite对URI处理的行为或动作,可以为一下四个当中的一个:

7.1、last:终止继续在本location块中处理接受到的URL,并将在本location中重新的URL作为一个新的URL,继续使用后面的各location块进行处理,该标志将重写后的URL重新再server块中执行,为重写后的URI转入到其他location块并继续处理的机制,nginx服务器的last处理超过10次循环之后将返回错误代码500,使用方法如下:

location / {
rewrite ^(/test/.*)/msie(.*)\..*$ $1/test/mp3/$2.html break;
rewrite ^(/test/.*)/other(.*)\.*$ $1/test/other/$2.html break;
}

注:如果URI在第二行被匹配成功并处理,Nginx服务器不会继续使用第三行的配置和匹配处理新的URL,而是让所有的location快重新匹配和处理新的URI,即一旦在本location中匹配成功一行,就跳出本location并在下一个location匹配,直到在下一个location匹配成功后再跳出下一个location继续下下一个,直到最后一个为止。

7.3、break:将你的URI作为一个新的URI,在本快中继续进行处理,该标志将重写后的地址在当前的location快中执行,不会将新的URI转向其他的location模块,如下:

nginx-相关功能分析  第四章
注意:如果第二行被匹配并处理成功,Nginx服务器将新的URI继续在本location块中使用第三行匹配和处理,新的URI始终在一个location之内匹配和处理,直到本location最后一个匹配条件。last一般写在server和if中,而break一般使用在location中
1、last一般写在server和if中,而break一般使用在location中
2、last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
3、break和last都会继续执行后面的rewrite指令,只是last会终止本location的匹配跳转到其他location,而break只会在当前location继续匹配,直到最后一条匹配结果为止,不会跳转到其他location。
nginx-相关功能分析  第四章

7.4、redirect:将重写后的URI返回给客户端,状态码为302,指明是临时重定向URI,主要用在replacement变量不是以http或https开头的情况下。

7.5、permanent:将重写后的URI返回给客户端,代码为301,注明是永久重定向。

注意:在使用flag的时候,

8、rewrite_log:用于配置是否开启URL重写日志的输出功能,用法如下:

rewrite_log on|off; #默认为off。,如果设置为开启,URL的相关日志将以notice级别的输出到error_log配置的文件当中。

9、set:用于设置一个新的变量,其用法结构为:

set  variable value;  #variable为变量的名称,要使用$作为变量的第一个字符,且变量名不能与nginx服务器预设的全局变量相同
value:为变量的值,可以是字符串、其他变量和变量组合等。

10、uninitialized_variable_warn:用于配置使用未初始化的变量时,是否记录告警日志,用法如下:

uninitialized_variable_warn on|off;

 4、root和alias:

root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location,如:

location /bbs {
root html; #必须要在html目录中创建一个bbs目录才可以访问,否则报错。
index index.html;
}

alias:定义路径别名,会把访问的路径重新定义到其指定的路径,如:

 location /newweb { #当访问newweb的时候,会显示alias定义的 /usr/local/nginx/html/newweb/里面的内容。
alias /usr/local/nginx/html/newweb/;
}

注:alias后面必须要用“/”结束,否则会找不到文件,而root要结合location,要么都有/,要么都没有/,如果一个有一个没有在访问的时候会出错。

三、Rewrite常用的全局变量:

1.Nginx服务器内置了很多预先定义好的内置变量,就要方便获取很多相关的服务器信息以及与请求相关的指令、参数当信息,可以更加方便的用户进行自定义的功能定义等,具体变量如下如下:

1.1、$args:变量中存放了URL中的指令,比如https://support.f5.com/csp/knowledge-center/software/BIG-IP?module=BIG-IP%20APM&version=11.6.1

1.2、$content_length:保存了请求报文头部中的content-lenght字段。

1.3、$content_type:保存了请求头部中的content-type字段。

1.4、$document_root:保存了针对当前资源的请求的系统根目录。

1.5、$document_uri:保存了当前请求中不包含指令的URI,注意是不包含请求的指令,

1.6、$host:存放了请求的服务器名称。

1.7、$http_user_agent:客户端浏览器的详细信息,如使用chrome和Firefox访问则显示如下:

Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36 #chrome的浏览器信息
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 #Firefox的浏览器信息

1.8、$http_cookie:客户端的cookie信息。

1.9、$limit_rate:如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0。

1.2.0:$remote_addr:存放了客户端的地址,注意是客户端的公网IP。

  Linux 查看客户端公网地址可以使用  

root@localhost /]# curl cip.cc

1.2.1:$remote_port:客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口。

1.2.2:$remote_user:已经经过Auth Basic Module验证的用户名。

1.2.3:$request_body_file:做反向代理时发给后端服务器的本地资源的名称。

1.2.4:$request_method:请求资源的方式,GET/PUT/DELETE等

1.2.5:$request_filename:当前请求的资源文件的路径名称,由root或alias指令与URI请求生成。

/usr/local/nginx//html/web/

1.2.6:$request_uri:包含请求参数的原始URI,不包含主机名,如:”/index.do?id=101020100&partner=”。

/web/

1.2.7:$squery_string:保存了URL请求的指令,与 $args相同。

1.2.8:$scheme:请求的协议,如ftp,https,http等。

1.2.9:$server_protocpl:保存了客户端请求资源使用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等。

1.3.0:$server_addr:保存了服务器的IP地址。

192.168.0.24

1.3.1:$server_name:服务器的主机名。

hfnginx.chinacloudapp.cn

1.3.2:$server_port:服务器的端口号。

80

1.3.3:$uri:与$document_uri相同,是一个不包含指令的uri地址。

如访问:hfnginx.chinacloudapp.cn/index.do?id=101020100&partner=,uri如下:
/index.do

四:rewrite 功能的具体使用: 

nginx rewrite功能使用模块ngx_http_rewrite_module,rewrite是nginx服务器的重要模块之一,它一方面实现了URL的重写功能,另一方面为Nginx服务器提供反向代理服务器的支持,使用如下:

1、proxy_pass:反向代理,将用户的请求代理至后端服务器:

nginx-相关功能分析  第四章

server {

listen 8090;
server_name localhost ;

location /aab {

proxy_pass http://10.2.61.23:8090/test/ ;     #nginx 代理在访问后端服务器时会将将 /aab 替换为 /test/ 路径,如果浏览器访问的是 /abb/ nginx 会代理成/test// 
}

}

server {

listen 8090;
server_name localhost ;

location /aab {

proxy_pass http://10.2.61.23:8090/test ;  # 在这个配置下访问 /aab 代理至后端就是 /test   ,访问 /aab/  代理至后端就是/test/   
}

}

server {

listen 8090;
server_name localhost ;

location /aab/ {

proxy_pass http://10.2.61.23:8090/test ;  #这种配置是错误的,访问/aab  返回 301 访问 /aab/  /aab// 一直循环。因此建议在配置时统一加 / 或者统一不加 /
}

}

日志:

代理服务器:

10.3.120.243 - - [22/Jan/2019:05:04:29 -0500] "GET /aab HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
10.3.120.243 - - [22/Jan/2019:05:04:29 -0500] "GET /aab/ HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
10.3.120.243 - - [22/Jan/2019:05:04:29 -0500] "GET /aab// HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
10.3.120.243 - - [22/Jan/2019:05:04:30 -0500] "GET /aab// HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
10.3.120.243 - - [22/Jan/2019:05:04:30 -0500] "GET /aab// HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"


nginx-相关功能分析  第四章

1.1访问结果:

如下方给出的请求URI,当指定资源路径的最后忘记添加斜杠“/”,就会产生301状态码 http://example.com/sample

nginx-相关功能分析  第四章

Connection: keep-alive

<html>
<head><title> Moved Permanently</title></head>
<body bgcolor="white">
<center><h1> Moved Permanently</h1></center>
<hr><center>nginx/1.14.</center>
</body>
</html>
GET /aab/ HTTP/1.1
Host: 10.2.61.22:
Connection: keep-alive
Upgrade-Insecure-Requests:
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9 HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Wed, 23 Jan 2019 02:04:49 GMT
Content-Type: text/html
Content-Length: 24
Connection: keep-alive
Last-Modified: Tue, 22 Jan 2019 08:59:52 GMT
ETag: "5c46db88-18"
Accept-Ranges: bytes proxy_8090 test success

2.使用正则匹配访问页面:

nginx-相关功能分析  第四章

server {

listen 8090;
server_name localhost ;

location ~* ^/aab/ { # ~*: #表示在匹配过程中不区分大小写字符,(可以通过正则表达式匹配),满足匹配条件为真,不满足问假。

            #在使用正则表达式时后端服务器必须存在相同路径,否则报错

proxy_pass http://10.2.61.23:8090 ;
}

}

#代理日志

10.3.120.243 - - [22/Jan/2019:22:16:08 -0500] "GET /aab/ HTTP/1.1" 404 571 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"

后端服务器日志

10.2.61.22 - - [22/Jan/2019:22:16:08 -0500] "GET /aab/ HTTP/1.0" 404 571 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"

  

nginx-相关功能分析  第四章

2.1:配置Nginx转发客户端IP:

#代理服务器
server { listen ;
server_name localhost ; location ~* ^/aab/ { # ~*: #表示在匹配过程中不区分大小写字符,(可以通过正则表达式匹配),满足匹配条件为真,不满足问假。 proxy_pass http://10.2.61.23:8090 ; proxy_set_header X-Forwarded-For $remote_addr; #将客户端地址插入http 数据包头并发往后端服务器,命名为X-Forwarded-For
  } 
  }
#后端代理服务器:
  
    server {
listen ;
server_name localhost;
set_real_ip_from 10.2.61.0/; #排除的代理地址
real_ip_header X-Forwarded-For;   #将http 头部中X-Forwarded-For 字段替换为 $remote_addr
real_ip_recursive on;    #在实际测试中如果命名为其他名称获得不到地址,经过测试得出的结果是只要前端代理插入了X-Forwarded-For 字段,在默认的日志"$http_x_forwarded_for"'就可以获取真实客户端地址
location / {          #也就是说并不需要nginx 添加--with-http_realip_module 模块来实现,但是网上大多数文档都是说要添加这个模块 - -
root html// ;
index index.html index.htm ; }
location /aab/ { root html ;
index index.html index.htm;
} }

   代理日志:
  10.1.255.156 - - [28/Jan/2019:08:14:10 -0500] "GET /aab/ HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
  后端nginx 服务器日志:
  10.1.255.156 - - [28/Jan/2019:08:14:10 -0500] "GET /aab/ HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36" "10.1.255.156"
  在后端配置文件中注释 #real_ip_header  X-Forwarded-For;
  10.2.61.22 - - [28/Jan/2019:08:36:38 -0500] "GET /aab/ HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36" "10.1.255.156"

五:临时重定向与永久重定向:

1.防盗链:

referer是记录打开一个页面之前记录是从哪个页面跳转过来的,如果别人只链接了自己网站图片或某个单独的资源,而不是网站的页面,这就是盗链,

location /image {
valid_referers none blocked www.baidu.com;
    if ($invalid_referer) {
      return 403;
} #none是用户正常在浏览器输入地址访问的请求连接 #blocked 类似于防火墙法则,只要不符合给定条件的就认定是不合法的,就拒绝访问。

2.通过rewrite完成地址重写:

301:永久重定向,一般资源都在服务器内部,客户端请求一次即可完成数据的返回。

302:临时重定向,当nginx作为代理服务器,并使用rewrite重写用户请求的URL的到其他服务器的时候,就是临时重定向。

nginx-相关功能分析  第四章
server {
server_name hfnginx.chinacloudapp.cn;
location / {
root html; #定义存放web的目录
index index.html;
#rewrite ^/bbs/(.*)$ http://www.weather.com.cn/$1; #将请求转发给其他服务器处理,是临时重定向,客户端需要在服务器返回报文中头部中查找到location字段并根据其中的路径到新服务器发送请求。
rewrite ^/bbs/(.*)$ /web/$1; #/web是在html目录下,也就是这里的跟就是html目录,将请求在服务器内存处理并返回给用户,是永久重定向的方式
}
}
nginx-相关功能分析  第四章

2.1临时重定向请求过程如下:

nginx-相关功能分析  第四章

2.2:永久重定向如下:

nginx-相关功能分析  第四章

六:rewrite后面的四个flag:

1.last:本次重写完成之后,重启下一轮检查,大多数情况下使用last,但是如果匹配写的有问题,会导致出现循环匹配,直到十次之后出错。

2.break:本次完成重写之后,直接执行后续数据操作,不再进行其他的条件匹配,在非跟location使用rewrite匹配的时候要使用break,避免导致循环。

3.redirect:返回302临时重定向,如果替换字段用http://开头则被使用。

4.permanent:返回301永久重定向。

七:对Apache实现上传下载分离:

 1.确认模块当中有dav模块:

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so

2、打开dav功能:

<Directory "/var/www/html">
Dav on #加一行

3、重启httpd:

[root@Server1 html]# systemctl  restart  httpd

4、将www目录改为apache权限,并使用curl -T命令测试上传:

nginx-相关功能分析  第四章
[root@Server1 html]# chown  apache:apache /var/www/html/ -R  #更改属主属组
[root@Server1 html]# curl -T /etc/issue http://192.168.0.202 #上传一个文件
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /issue has been created.</p> #返回上传成功
</body></html> 验证:

 [root@Server1 html]# ls /var/www/html/
    form index.html issue

nginx-相关功能分析  第四章

5、客户端使用浏览器访问测试:
nginx-相关功能分析  第四章

6、通过Nginx实现下载和上传的分离:

nginx-相关功能分析  第四章
server {
server_name hfnginx.chinacloudapp.cn;
location / {
#root html;
index index.html;
proxy_pass http://192.168.0.201;
if ($request_method = "PUT"){ #假如请求的方法是上传
proxy_pass http://192.168.0.202;
}
}
}
nginx-相关功能分析  第四章

7、测试上传是否生效:

nginx-相关功能分析  第四章

8、服务器验证上传的文件:

nginx-相关功能分析  第四章

 八:几个代表性的例子:

1.location匹配定义的目录:

nginx-相关功能分析  第四章
location = / {  #精确匹配,/后面不能加任何字符串,符合此条件就直接返回数据,不再像下匹配。
if (-d $request_filename) {
root /usr/local/nginx/html/; #当用户访问newweb的时候,则显示此目录的内容,除此之外访问其他的任何目录都不匹配。
  [动作A]
} location / {
# 因为所有的地址都以/开头,所以这条规则将匹配到所有请求,但是非精确匹配会采取正则和最长字符串会优先匹配,因此还会向下继续匹配,比如当访问/bbs的时候,还需要看下面是否更精确的匹配。
[ 动作B]
}
location /documents/ {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
# 如果后面的正则表达式都没有匹配到,就匹配这一条
[动作C]
}
location ^~ /images/ { #匹配任何以/images/ 开头的任何请求并且停止搜索,后面任何正则表达式将不会被测试。
# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
[动作D]
}
location ~* \.(gif|jpg|jpeg)$ { #~*为不区分大小写
# 匹配所有以 gif,jpg或jpeg 结尾的请求
# 然而,所有请求/images/下的图片会被动作D匹配处理,因为动作D有^~会优先匹配并终止匹配,所以到达不了这一条正则
[动作E]
}
location /images/ {
# 字符匹配到 /images/,继续往下,会发现 ^~ 存在,如果动作D存在,则这一条就不生效。
[动作F]
} location /images/abc {
#最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在,如果D存在,则这一条就不生效。
#F与G的放置顺序是没有关系的
[动作G]
} location ~ /images/abc/ {
# 动作D存在,这一条不生效,如果注销动作D,则会优先最长匹配 动作G 开头的地址,然后向下匹配,到这一条的时候就会匹配并生效。
[ configuration H ]
}
匹配优先级,顺序 no优先级:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/) 上面的匹配结果
按照上面的location写法,以下的匹配示例成立: / -> config A
精确完全匹配,即使/index.html也匹配不了 /downloads/download.html -> config B
匹配B以后,往下没有任何匹配,采用B /images/1.gif -> configuration D
匹配到F,往下匹配到D,停止往下 /images/abc/def -> config D
最长匹配到G,往下匹配D,停止往下
你可以看到 任何以/images/开头的都会匹配到D并停止,FG写在这里是没有任何意义的,H是永远轮不到的,这里只是为了说明匹配顺序 /documents/document.html -> config C
匹配到C,往下没有任何匹配,采用C /documents/1.jpg -> configuration E
匹配到C,往下正则匹配到E /documents/Abc.jpg -> config CC
最长匹配到C,往下正则顺序匹配到CC,不会往下到E
nginx-相关功能分析  第四章

2.if判断语句:

nginx-相关功能分析  第四章
if ($http_user_agent ~ MSIE) { #如果客户端是微软的IE浏览器,就将请求rewrite到msie目录下。
rewrite ^(.*)$ /msie/$1 break;
} if ($http_cookie ~* "id=([^;]+)(?:;|$)") { # 如果cookie匹配正则,就设置变量$id等于正则引用部分
set $id $1; 设置$id等于正则第一个括号内匹配的部分
} if ($request_method = POST) { #如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
return 405;
} if ($slow) { #限速,$slow可以通过 set 指令设置
limit_rate 10k;
} if (!-f $request_filename){ #如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
break;
proxy_pass http://127.0.0.1;
} if ($args ~ post=140){ #如果query string中包含"post=140",永久重定向到example.com
rewrite ^ http://example.com/ permanent;
}
nginx-相关功能分析  第四章

3、关于防盗链:

nginx-相关功能分析  第四章
location ~* \.(gif|jpg|png|swf|flv)$ { # 防盗链设置,对于后缀是gif、jgp等格式的生效
valid_referers none blocked a.com *.a.com; #定义允许访问的请求链接
if ($invalid_referer) {
return 404;
}
} none:在浏览器输入网站域名直接访问的请求,需要允许访问的
blocked:有referer首部,但是referer首部被清除了,一般是防火墙改过的请求
server_name:带服务器名称的,一般是本机或其他服务器的请求,a.com和*.a.com是本公司的域名,要允许访问于是要先允许本机的访问,再禁止其他服务器的访问
nginx-相关功能分析  第四章

4.实际使用建议:

nginx-相关功能分析  第四章
实际使用中,个人觉得至少有三个匹配规则定义,如下:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http://tomcat:8080/
} 如果其他可以精确匹配的路径,也可以精确匹配,这样会加快Nginx处理请求。
nginx-相关功能分析  第四章

5、常用的正则匹配:

nginx-相关功能分析  第四章
. : 匹配除换行符以外的任意字符
? : 重复0次或1次
+ : 重复1次或更多次
* : 重复0次或更多次
\d :匹配数字
^ : 匹配字符串的开始
$ : 匹配字符串的介绍
{n} : 重复n次
{n,} : 重复n次或更多次
[c] : 匹配单个字符c
[a-z] : 匹配a-z小写字母的任意一个
小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。正则里面容易让人困惑的是\转义特殊字符。
nginx-相关功能分析  第四章

6、根据图片尺寸rewrite请求链接:

rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;
#将/images/bla_500x400.jpg的文件请求,重写到/resizer/bla.jpg?width=500&height=400地址,并会继续尝试匹配location。

7、域名重写:

nginx-相关功能分析  第四章
server {
server_name hfnginx.chinacloudapp.cn; #凡是访问hfnginx.chinacloudapp.cn都会重定向到http://www.baidu.com
location / {
root html;
index index.html;
rewrite ^/ http://www.baidu.com;
}
}
nginx-相关功能分析  第四章

8、完整的例子引用:

nginx-相关功能分析  第四章
http {
# 定义image日志格式
log_format imagelog '[$time_local] ' $image_file ' ' $image_type ' ' $body_bytes_sent ' ' $status;
# 开启重写日志
rewrite_log on; server {
root /home/www; location / {
# 重写规则信息
error_log logs/rewrite.log notice;
# 注意这里要用‘’单引号引起来,避免{}
rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4;
# 注意不能在上面这条规则后面加上“last”参数,否则下面的set指令不会执行
set $image_file $3;
set $image_type $4;
} location /data {
# 指定针对图片的日志格式,来分析图片类型和大小
access_log logs/images.log mian;
root /data/images;
# 应用前面定义的变量。判断首先文件在不在,不在再判断目录在不在,如果还不在就跳转到最后一个url里
try_files /$arg_file /image404.html;
}
location = /image404.html {
# 图片不存在返回特定的信息
return 404 "image not found\n";
}
}