Location 语法解释
location 大致可以分成3种
- 精准匹配
- 一般匹配
- 正则匹配
location [=|~|~*|^~] /uri/ { … }
location = url { … } # 精准匹配
location url { … } # 一般匹配
location ~ url { … } # 正则匹配
符号解释
符号 | 解释 |
---|---|
= | 开头表示精确匹配 |
^~ | 开头表示 url 以某个常规字符串开头,理解为匹配 url 路径即可。 |
~ | 开头表示区分大小写的正则匹配 |
~* | 开头表示不区分大小写的正则匹配 |
! ~ 和 ! ~ * | 分别为区分大小写不匹配及不区分大小写不匹配 的正则 |
/ | 通用匹配,任何请求都会匹配到 |
如何发挥作用
首先看有没有精准匹配,如果有则停止匹配过程
location = patt {
config A
}
如果 $url = patt,那么算匹配成功,则使用 config A。
示例:
location =/ {
root /var/www/html/;
index index.htm index.html;
}
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
如果访问 http://xxx.com/
定位流程是:
- 精准匹配中 “/”,得到 index 页为 index.html
- 再次访问 /index.htm ,此次内部跳转 URI 已经是 “/index.htm”,目前根目录为 /usr/local/nginx/html
- 最终结果,访问/usr/local/nginx/html 下的 index.htm。
现在加入正则,示例1:
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
location ~ image {
root /var/www/html/;
index index.html;
}
如果此时访问 http://xx.com/image/test.png (假设此时 /var/www/html/ 下有 test.png 文件)
此时,“ / ”与 “ /image/test.png ”匹配,同时,“ image ”正则与“ /image/test.png ”也能匹配。最终图片会真正访问 /var/www/html/image/test.png
示例2:
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
location /dudulu {
root /var/www/html/;
index index.html;
}
对于 uri “ /dudulu ”,两个 location 的 patt ,都能匹配到他们,即 “ / ”能从左前缀匹配 “ /dudulu ”,“ /dudulu ”也能左前缀匹配“ /dudulu ”。
此时真正访问的是 /var/www/html/index.html ,原因:“ /dudulu ”匹配的更长,所有使用这个。
下面从网上找到三个匹配规则定义
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ { //以xx开头
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { //以xx结尾
root /webroot/res/;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
location / {
proxy_pass http://tomcat:8080/
}
总结:location 的命中过程
- 先判断精准命中,如果命中,立即返回结果并结束解析过程
- 判断普通命中,若干个如果有多个命中,“记录”下来“最长”的命中结果(注意:记录但不结束,最长的为准)
- 继续判断正则表达式的解析结果,按配置里的正则表达式顺序为准,由上到下开始匹配,一旦匹配成功一个,立即返回结果,并且结束解析过程
延伸:1、普通命中,顺序无所谓,是因为按命中的长短来确定的。2、正则命中,顺序有所谓,因为从前往后命中。
Rewrite 重写 语法解释
重写中用到的指令
指令 | 解释 |
---|---|
if () {} | 设定条件,在进行重写 |
set | 设置变量 |
return | 返回状态码 |
break | 跳出 rewrite |
rewrite | 重写 |
if 语法的格式
#if 空格 {条件}{
# 重写模式
#}
判断的表达式条件
- -f和!-f用来判断是否存在文件
- -d和!-d用来判断是否存在目录
- -e和!-e用来判断是否存在文件或目录
- -x和!-x用来判断文件是否可执行
- = 用来判断相等,用于字符串的比较
- ~ 用来正则匹配 (区分大小写)(~ * 不区分大小写)
示例:
if ( $remote_addr = 192.168.1.14 ){
return 430;
}
if ( $http_user_agent ~ MSIE ){
rewrite ^.*$/dudulu.html;
break; # 不加 break 会循环重定向
}
if ( !-e $document_root $fastcgi_scrpt_name ){
rewrite ^.*$/404.html break;
}
# 注:此处还要加 break
以 xx.com/dudulu.html 这个不存在的页面为例
观察服务器日志文件可以发现,日志中显示的访问路径依然是 GET /dudulu.html HTTP/1.1
提示:服务器内部的 rewrite 和 302 跳转不一样
跳转的话 url 都变了,变成重新 http 请求 404.html ,而内部的 Rewrite,上下文没变,就是说 astcgi_scrpt_name 仍然是 dudulu.html ,因此会循环重定向。
评论区