问题一:
曾经遇到的一个问题:一个server下配置多个 location
location ^~ /admin {
alias /var/www/admin/;
index regist.html;
}
location / {
root /data/html/;
index index.html index.html;
}
root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。
root的处理结果是:root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的定义。
还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的。。。而root则可有可无~~
问题二、
location 块中,
root
和alias
指令后的路径最后面,有没有 "/" 的区别如下:
location ^~ /dev-popularize/ {
# root 指令中:如果后面没有 "/" 则 dist 这个目录下,必须有 dev-popularize 这个目录,然后你的静态资源文件都在这个目录下
# root /Users/wxq/Desktop/shounaer/dist;
# root 指令中:如果后面有 "/" 则 dist 这个目录下,不需要有 dev-popularize 这个目录,你的静态资源文件直接放在dist目录下就行
# root /Users/wxq/Desktop/shounaer/dist/;
# alias 指令中:如果后面没有有 '/' ,则 dist 目录下,无论有没有dev-popularize 都不行,会报 403,不知道为啥。。。
alias /Users/wxq/Desktop/shounaer/dist;
# alias 指令中:如果后面有 '/' ,则 dist 目录下,直接放你的静态资源文件就行
# alias /Users/wxq/Desktop/shounaer/dist/;
index regist.html;
}
语法规则: location [ = | ~ | ~ * | ^~ ] /uri/ { … }
1、以 =
开头,表示精确匹配
# 精确匹配,必须是127.0.0.1/
location = / {
#规则A
}
# 精确匹配,必须是127.0.0.1/login
location = /login {
#规则B
}
2、以 ^~
开头,表示uri以某个常规字符串开头,理解为匹配 url路径即可
nginx不对url做编码,因此请求为/static/20%/aa
,可以被规则^~ /static/ /aa
匹配到(注意是空格)
。
## 非精确匹配,并且不区分大小写,比如127.0.0.1/static/js.
location ^~ /static/ {
#规则C
}
3、~
开头,表示区分大小写
的正则匹配
## 区分大小写,以gif,jpg,js结尾
location ~ \.(gif|jpg|png|js|css)$ {
#规则D
}
4、~*
开头,表示不区分大小写
的正则匹配
## 不区分大小写,匹配.png结尾的
location ~* \.png$ {
#规则E
}
5、!~
和!~*
分别为区分大小写不匹配
及不区分大小写不匹配
的正则
## 区分大小写,匹配不以.xhtml结尾的
location !~ \.xhtml$ {
#规则F
}
location !~* \.xhtml$ {
#规则G
}
6、/
通用匹配,任何请求都会匹配到。
## 什么都可以
location / {
#规则H
}
7、匹配顺序
多个location配置的情况下匹配顺序为:
首先匹配=
;
其次匹配^~
;
再其次是按文件中顺序的正则匹配;
最后是交给 / 通用匹配;
当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
那么产生的效果如下:
访问根目录/, 比如http://localhost/ //将匹配规则A
访问 http://localhost/login 将匹配规则B
访问 http://localhost/register 则匹配规则H
访问 http://localhost/static/a.html 将匹配规则C
访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用, 而 http://localhost/static/c.png 则优先匹配到 规则C
访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。
访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。
访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。
8、其他
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
// 这里是直接转发给后端应用服务器了,也可以是一个静态首页
1)、第一个必选规则
location = / {
proxy_pass http://127.0.0.1:3000/
}
2)、第二个必选规则
第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
有两种配置模式,目录匹配
和后缀匹配
,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
3)、第三个规则就是通用规则,用来转发动态请求到后端应用服务器
location /api/ {
proxy_pass http://127.0.0.1:3000/api/
}
9、Rewrite语法
last – 表示完成rewrite
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301
1、下面是可以用来判断的表达式:
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
2、下面是可以用作判断的全局变量
例: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:D:\nginx/html
$request_filename:D:\nginx/html/test1/test2/test.php
参考这篇文章:《nginx中location、rewrite用法总结》的Rewrite部分
10、Redirect语法
server {
listen 80;
server_name start.igrow.cn;
index index.html index.php;
root html;
if ($http_host !~ “^star\.igrow\.cn$" {
rewrite ^(.*) http://star.igrow.cn$1 redirect;
}
}
11、if 模块
详情请:参考这篇文章《nginx中location、rewrite用法总结》的 if 部分
// 如果用户设备为IE浏览器的时候,重定向 。如果UA包含"MSIE",rewrite请求到/msid/目录下
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
//如果cookie匹配正则,设置变量$id等于正则引用部分
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
//如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
if ($request_method = POST) {
return 405;
}
//限速,$slow可以通过 set 指令设置
if ($slow) {
limit_rate 10k;
}
//如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
}
//如果query string中包含"post=140",永久重定向到example.com
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
}
//防盗链
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.com www.lfa.com;
if ($invalid_referer) {
return 404;
}
}
12、防盗链
location ~* \.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}
说明:
如果valid_referers
条件判断未通过,nginx 则会赋值invalid_referer
为true
语法:valid_referers none | blocked | server_names | string ...;
参数说明:
none
: 不允许 “Referer” 来源头部为空的情况
blocked
: 不允许“Referer”值为空情况,有可能Referer的值被代理或者防火墙删除
server_names
: “Referer”来源头部包必须含当前的server_names (当前域名)可以多个
13、根据文件类型设置过期时间
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
expires 1h;
break;
}
}
14、禁止访问某个目录
location ~* \.(txt|doc)${
root /data/www/wwwroot/linuxtone/test;
deny all;
}
15、一些可用的全局变量
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$request_method : 客户端请求的动作,通常为GET或POST。
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri : 不包含请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri相同。
$query_string
$args : 这个变量等于请求行中的参数,同$query_string
$document_root : 当前请求在root指令中指定的值。
$limit_rate : 这个变量可以限制连接速率。
$request_body_file
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$scheme : HTTP方法(如http,https)。
$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
网友评论