location匹配
匹配的符号说明
表示符号 | 符号说明 |
= | 表示精确匹配,只有完全匹配上才能生效 |
^~ | 表示uri以某个常规字符串开头 |
~ | 正则匹配(区分大小写) |
~* | 正则 (不区分大小写) |
! ~ | 区分大小写不匹配的正则 |
! ~ * | 不区分大小写不匹配的正则 |
/ | 任何请求都会匹配 |
匹配优先级
1> 匹配=,如果匹配成功,则停止其他匹配 (先进行前缀匹配,再进行正则匹配)
2> 普通字符串的匹配,和其在配置文件中的顺序无关,而是与匹配的长短有关,如果匹配成功的 location 使用了 ^~ ,则停止匹配,否则进行正则匹配(如果正则匹配成功,则使用正则匹配的结果,如果正则匹配不成功,则使用此处匹配的结果) ^~ 若最长前缀匹配含有前面这个字符,则终止后面的正则匹配
3> 正则匹配,按照正则匹配在配置文件中出现的顺序,成功则停止匹配
4> 以上都没匹配成功,则使用 / 通配符匹配
5> 有时候为了避免匹配成功的普通字符串再继续进行正则匹配,会使用 ^~ 符号
6> 在前缀匹配中,寻找并记录最长前缀匹配(两个location,/abc和/abc/def 那么带uri/abc/def/a.jpg的请求匹配的最长前缀就是/abc/def)
顺序 no优先级:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~ , ~* 正则顺序) > (location 部分起始路径) > (/)
[root@ nginx]# cat nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name 10.252.71.219;
# 精确匹配 / ,主机名后面不能带任何字符串
location =/ { #A
root /data/nginxA/;
index index.html index.htm;
}
# 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
# 但是正则和最长字符串会优先匹配
location / { #B
root /data/nginxB/;
index index.html index.htm;
}
# 匹配任何以 /doc/ 开头的地址,匹配符合以后,还要继续往下搜索
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
location /doc/ { #C
root /data/nginxC/;
index index.html index.htm;
}
# 匹配任何以 /doc/ 开头的地址,匹配符合以后,还要继续往下搜索
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
location ~ /doc/Abc { #D
root /data/nginxD/;
index index.html index.htm;
}
# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
location ^~ /image/ { #E
root /data/nginxE/;
index index.html index.htm;
}
# 匹配所有以 gif,jpg或jpeg 结尾的请求 不区分大小写
# 然而,所有请求 /images/ 下的图片会被 config E 处理,因为 ^~ 到达不了这一条正则
location ~* \.(gif|jpg|jpeg)$ { #F
root /data/nginxF/;
index index.html index.htm;
}
# 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
# F与G的放置顺序是没有关系的
location /image/abc { #G
root /data/nginxG/;
index index.html index.htm;
}
# 只有去掉 config E 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用
location ~ /image/abc { #H
root /data/nginxH/;
index index.html index.htm;
}
}
include /etc/nginx/conf.d/*.conf;
}
匹配示例
访问根目录http://localhost/ 将匹配规则A
访问 http://localhost/doc 将匹配规则C,http://localhost/file(不是doc) 则匹配规则B
访问 http://localhost/image/a.html 将匹配规则E
访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则F,而 http://localhost/image/c.png 则优先匹配到规则E
建议
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网也如此
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
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/
}
示例
普通字符串匹配
location ^~ /helloworld { #1
return 601;
}
#location /helloworld { #2
# return 602;
#}
location ~ /helloworld {
return 603;
}
访问http://localhost/helloworld/test,返回601
如果将上面的块注释,中间的块放开注释,则返回603,因为匹配到普通字符串没有带^~,会继续进行正则匹配
普通字符串长短匹配规则
location /helloworld/test/ {
return 601;
}
location /helloworld/ {
return 602;
}
普通字符串的匹配和配置文件中的顺序无关,而是与匹配的长短有关。
访问http://localhost/helloworld/test/a.html,返回601
http://localhost/helloworld/a.html,返回602
正则匹配和其在配置文件中的顺序有关
location /helloworld/test/ { #1
return 601;
}
location ~ /helloworld { #2
return 602;
}
location ~ /helloworld/test { #3
return 603;
}
访问http://localhost/helloworld/test/a.html,返回602
交换#2和#3调换顺序
访问http://localhost/helloworld/test/a.html,返回603
root和alias的区别
下面这两种写法的区别(html是nginx的默认访问根目录):
location /dir1/ {
alias html/dir1;
}
location /dir1/ {
root html/dir1;
}
当访问http://ip/dir1/1.html的时候,如果是第一种配置,则会在html/dir1目录下找1.html文件,
如果是第二种配置,则会在html/dir1/dir1目录下找1.html文件
root是在全目录下继续加上location的路径
proxy_pass 加/和不加/
proxy_pass代理的时候,下面两种写法的区别:
location /proxy/ {
proxy_pass http://proxy_ip;
}
location /proxy/ {
proxy_pass http://proxy_ip/;
}
当访问http://ip/proxy/1.html的时候,如果是第一种配置,则代理访问http://proxy_ip/proxy/1.html,
如果是第二种配置,则代理访问http://proxy_ip/1.html