nginx-相关功能分析 第四章
# 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支持的集中调度算法:
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服务器的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引用截取的值,如下:
if ($http_user_agent ~ MSIE) { #if语句尽量用在location当中,尽量不要在http或server中使用,会出现莫名的错误。
#判断客户端的浏览器中是否含有MSIE的字符串,如果包含则为true
} #########################################
if ($http_cookie ~* "id="([^;]+)(?:;)") {
#Nginx配置,可以使用$!和$2获取截取到的值,如:
# set $id $1; 将截取到的id的值赋值给$id变量以备后用
}
注意:整个正则表达式一般不需要加引号,但是如果含有右大括号"}"或者分分号";"的时候,就必须要给整个正则表达式加上引号""
3、文件和目录测试:单目测试,判断文件或者目录是否存在
3.1 -f和! -f:判断请求的文件是否存在和是否不存在
-f 表示如果请求的文件存在,则if指令为true,如果请求的文件不存在,则if指令为false。使用! -f的时候,如果请求的文件不存在但是目录存在,if指令认为条件为true,如果请求的文件和目录都不存在,则if指令认为条件为false,如果请求的文件存在,也为false,如下:
if (-f $request_filename) {
#判断请求的文件是否存在
} if (! -f $request_filename) {
#判断请求的文件是否不存在
}
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进行匹配。
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。
注: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服务器将新的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。
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:反向代理,将用户的请求代理至后端服务器:
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"
1.1访问结果:
如下方给出的请求URI,当指定资源路径的最后忘记添加斜杠“/”,就会产生301状态码 http://example.com/sample
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.使用正则匹配访问页面:
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"
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的到其他服务器的时候,就是临时重定向。
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目录,将请求在服务器内存处理并返回给用户,是永久重定向的方式
}
}
2.1临时重定向请求过程如下:
2.2:永久重定向如下:
六: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命令测试上传:
[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
5、客户端使用浏览器访问测试:
6、通过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;
}
}
}
7、测试上传是否生效:
8、服务器验证上传的文件:
八:几个代表性的例子:
1.location匹配定义的目录:
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
2.if判断语句:
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;
}
3、关于防盗链:
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是本公司的域名,要允许访问于是要先允许本机的访问,再禁止其他服务器的访问
4.实际使用建议:
实际使用中,个人觉得至少有三个匹配规则定义,如下:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
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处理请求。
5、常用的正则匹配:
. : 匹配除换行符以外的任意字符
? : 重复0次或1次
+ : 重复1次或更多次
* : 重复0次或更多次
\d :匹配数字
^ : 匹配字符串的开始
$ : 匹配字符串的介绍
{n} : 重复n次
{n,} : 重复n次或更多次
[c] : 匹配单个字符c
[a-z] : 匹配a-z小写字母的任意一个
小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。正则里面容易让人困惑的是\转义特殊字符。
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、域名重写:
server {
server_name hfnginx.chinacloudapp.cn; #凡是访问hfnginx.chinacloudapp.cn都会重定向到http://www.baidu.com
location / {
root html;
index index.html;
rewrite ^/ http://www.baidu.com;
}
}
8、完整的例子引用:
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";
}
}
nginx-相关功能分析 第四章的更多相关文章
- 2017.2.7 开涛shiro教程-第六章-Realm及相关对象(四)
原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第六章 Realm及相关对象(四) 1.Subject的代码结构 ...
- 《Linux内核设计与实现》读书笔记 第四章 进程调度
第四章进程调度 进程调度程序可看做在可运行太进程之间分配有限的处理器时间资源的内核子系统.调度程序是多任务操作系统的基础.通过调度程序的合理调度,系统资源才能最大限度地发挥作用,多进程才会有并发执行的 ...
- 精通Web Analytics 2.0 (6) 第四章:点击流分析的奇妙世界:实际的解决方案
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第四章:点击流分析的奇妙世界:实际的解决方案 到开始实际工作的时候了.哦耶! 在本章中,您将了解到一些最重要的网络分析报告,我将 ...
- 05 技术内幕 T-SQL 查询读书笔记(第四章)
第四章 子查询:在外部查询内嵌套的内部查询(按照期望值的数量分为,标量子查询 scalar subqueries,多值子查询multivalued subqueries)(按照子查询对外部查询的依赖性 ...
- 《Linux内核设计与实现》课本第四章自学笔记——20135203齐岳
<Linux内核设计与实现>课本第四章自学笔记 进程调度 By20135203齐岳 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统.多任务操作系统使多个进程处于堵 ...
- 第四章 使用Docker镜像和仓库(二)
第四章 使用Docker镜像和仓库(二) 回顾: 开始学习之前,我先pull下来ubuntu和fedora镜像 [#9#cloudsoar@cloudsoar-virtual-machine ~]$s ...
- 第四章 跨平台图像显示库——SDL 第一节 与SDL第一次亲密接触
http://blog.csdn.net/visioncat/article/details/1596576 GCC for Win32 开发环境介绍(5) 第四章 跨平台图像显示库——SDL 第一节 ...
- [Effective Java]第四章 类和接口
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- [转]Windows Shell 编程 第四章 【来源 http://blog.csdn.net/wangqiulin123456/article/details/7987933】
第四章 文件的本质 以前,所有文件和目录都有一个确定的属性集:时间,日期,尺寸,以及表示‘只读的’,‘隐藏的,‘存档的’,或‘系统的’状态标志.然而,Windos95(及后来的WindowsNT4.0 ...
随机推荐
- C#GDI+ 绘制线段(实线或虚线)、矩形、字符串、圆、椭圆
C#GDI+ 绘制线段(实线或虚线).矩形.字符串.圆.椭圆 绘制基本线条和图形 比较简单,直接看代码. Graphics graphics = e.Graphics; //绘制实线 )) { pen ...
- react proxy 报错
react项目中,package.json中proxy的配置如下 "proxy": { "/api/rjwl": { "target": & ...
- [原]获取openstack-pike安装包
linux version: CentOS 7.5.1804 #进入仓库配置目录 cd /etc/yum.repo.d/ #批量重命名所有文件 for files in `ls *`; do mv $ ...
- Msf的一些常用操作
payload的几个常用生成 生成windows下的反弹木马 msfvenom -p windows/meterpreter/reverse_tcp LHOST=60.205.212.140 LPOR ...
- 【C++ 实验5 类和对象】
1. #include <iostream> #include <vector> #include <string> using namespace std; // ...
- 做二级菜单时候遇到的关于事件冒泡以及mouseover和mouseenter的不同
二级菜单作为最普通小组件,我遇到了坑. <style> .wrapper { height: 150px; border: 1px solid; width: 150px; } .wrap ...
- React 学习之路 (一)
先说一说对React的体验,总结 首先react相对angular来说入手简单暴力,在学习的这段时间里发现: 我们每天做的事就是在虚拟DOM上创建元素然后在渲染到真实的DOM中 渲染到真实DOM上的R ...
- javascript的数组之from()
Array.from()方法从一个类似数组或可迭代对象中创建一个新的数组实例. const arr = [1, 2, 3]; Array.from(arr); //[1, 2, 3] Array.fr ...
- mysql日志分类
mysql的日志分类: (1)错误日志:记录mysql服务的启动,运行,停止mysql服务时出现的问题 [mysqld] log_error=[/path/filename] (2)通用查询日志:记录 ...
- python全栈开发 * 24 知识点汇总 * 180705
24 模块-------序列化一.什么是模块 模块:py文件就是一个模块.二.模块的分类:(1)内置模块 (登录模块,时间模块,sys模块,os模块)(2)扩展模块 (itchat 微信有关,爬虫,b ...