🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
语法规则: location \[=|~|~\*|^~\] /uri/ { … } 语法规则: location空格\[=|~|~\*|^~\]空格/uri/ { … } \= 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。 ~ 开头表示区分大小写的正则匹配 ~\*  开头表示不区分大小写的正则匹配 !~和!~\*分别为区分大小写不匹配及不区分大小写不匹配 的正则 / 通用匹配,任何请求都会匹配到。 多个location配置的情况下匹配顺序为(参考资料而来,还未实际验证,试试就知道了,不必拘泥,仅供参考): 首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。 ### ginx正则相关 ~      为区分大小写字母的匹配。 ~\*     不区分大小写字母的匹配(匹配aa的同时也匹配AA、Aa、aA)。 !~     与~相反,表示区分大小写的不匹配 !~\*    与~\*相反,表示不分区大小写的不匹配 .     匹配除换行符以外的任意字符 \w     匹配字母、数字、下划线或汉字 \s     匹配任意的空白符 \d     匹配数字 \b     匹配单词的开始或结束 ^     匹配字符串的开始 $     匹配字符串的结束 \*     重复零次或更多次 \+     重复一次或更多次 ?     重复零次或一次 {n}     重复n次 {n,}     重复n次或更多次 {n,m}     重复n到m次 \*?     重复任意次,但尽可能少重复 +?     重复1次或更多次,但尽可能少重复 ??     重复0次或1次,但尽可能少重复 {n,m}?     重复n到m次,但尽可能少重复 {n,}?     重复n次以上,但尽可能少重复 \W     匹配任意不是字母,数字,下划线,汉字的字符 \S     匹配任意不是空白符的字符 \D     匹配任意非数字的字符 \B     匹配不是单词开头或结束的位置 [^x]     匹配除了x以外的任意字符 [^aeiou]     匹配除了aeiou这几个字母以外的任意字符 捕获     (exp)     匹配exp,并捕获文本到自动命名的组里 (?exp)     匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) (?:exp)     匹配exp,不捕获匹配的文本,也不给此分组分配组号 零宽断言     (?=exp)     匹配exp前面的位置 (?<=exp)     匹配exp后面的位置 (?!exp)     匹配后面跟的不是exp的位置 (?<!exp)     匹配前面不是exp的位置 注释     (?#comment)     这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 ## location匹配顺序 1. "="前缀指令匹配,如果匹配成功,则停止其他匹配 2. 普通字符串指令匹配,顺序是从长到短,匹配成功的location如果使用^~,则停止其他匹配(正则匹配) 3. 正则表达式指令匹配,按照配置文件里的顺序,成功就停止其他匹配 4. 如果第三步中有匹配成功,则使用该结果,否则使用第二步结果 ## 注意点 1. 匹配的顺序是先匹配普通字符串,然后再匹配正则表达式。另外普通字符串匹配顺序是根据配置中字符长度从长到短,也就是说使用普通字符串配置的location顺序是无关紧要的,反正最后nginx会根据配置的长短来进行匹配,但是需要注意的是正则表达式按照配置文件里的顺序测试。找到第一个比配的正则表达式将停止搜索。 2. 一般情况下,匹配成功了普通字符串location后还会进行正则表达式location匹配。有两种方法改变这种行为,其一就是使用“=”前缀,这时执行的是严格匹配,并且匹配成功后立即停止其他匹配,同时处理这个请求;另外一种就是使用“^~”前缀,如果把这个前缀用于一个常规字符串那么告诉nginx 如果路径匹配那么不测试正则表达式。 ## 匹配模式及顺序 ```   location = /uri    =开头表示精确匹配,只有完全匹配上才能生效。   location ^~ /uri   ^~ 开头对URL路径进行前缀匹配,并且在正则之前。   location ~ pattern  ~开头表示区分大小写的正则匹配。   location ~* pattern  ~*开头表示不区分大小写的正则匹配。   location /uri     不带任何修饰符,也表示前缀匹配,但是在正则匹配之后。   location /      通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default。  ``` ## 案例 测试"^~"和"~",nginx配置如下。浏览器输入http://localhost/helloworld/test,返回601。如将#1注释,#2打开,浏览器输入http://localhost/helloworld/test,返回603。注:#1和#2不能同时打开,如同时打开,启动nginx会报nginx: \[emerg\] duplicate location "/helloworld"...,因为这两个都是普通字符串。 ~~~ location ^~ /helloworld { #1 return 601; } #location /helloworld { #2 # return 602; #} location ~ /helloworld { return 603; } ~~~ 测试普通字符串的长短(普通字符串的匹配与顺序无关,与长短有关)。浏览器输入http://localhost/helloworld/test/a.html,返回601。浏览器输入http://localhost/helloworld/a.html,返回602。 ~~~ location /helloworld/test/ { #1 return 601; } location /helloworld/ { #2 return 602; } ~~~ 测试正则表达式的顺序(正则匹配与顺序相关)。浏览器输入http://localhost/helloworld/test/a.html,返回602;将#2和#3调换顺序,浏览器输入http://localhost/helloworld/test/a.html,返回603 ~~~ location /helloworld/test/ { #1 return 601; } location ~ /helloworld { #2 return 602; } location ~ /helloworld/test { #3 return 603; } ~~~ 例子,有如下匹配规则: ~~~ location = / { #规则A (访问网站根目录才会走这比如http://localhost/) =开头表示精确匹配 } location = /login { #规则B(http://localhost/login) } location ^~ /static/ { #规则C (http://localhost/static/a.html) ^~开头表示以常规字符串开头的url路径 } location ~ \.(gif|jpg|png|js|css)$ { #规则D (访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而 http://localhost/static/c.png 则优先匹配到 规则C) ~开头表示区分大小写的匹配 } location ~* \.png$ { #规则E (访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写) ~*开头表示不区分大小写的正则匹配 } location !~ \.xhtml$ { #规则F !~开头表示区分大小写的不匹配 } location !~* \.xhtml$ { #规则G !~*开头表示不区分大小写的不匹配 } location / { #规则H (http://localhost/register) } ~~~ 访问 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作为方向代理服务器存在。 那么产生的效果如下: 访问根目录/, 比如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作为方向代理服务器存在。 所以实际使用中,通常至少有三个匹配规则定义,如下: ~~~ #直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。 #这里是直接转发给后端应用服务器了,也可以是一个静态首页 # 第一个必选规则 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/ } ~~~ 三、ReWrite语法 last– 基本上都用这个Flag。 break– 中止Rewirte,不在继续匹配 redirect– 返回临时重定向的HTTP状态302 permanent– 返回永久重定向的HTTP状态301 注:last和break最大的不同在于 \- break是终止当前location的rewrite检测,而且不再进行location匹配 - last是终止当前location的rewrite检测,但会继续重试location匹配并处理区块中的rewrite规则 1、下面是可以用来判断的表达式: \-f和!-f用来判断是否存在文件 \-d和!-d用来判断是否存在目录 \-e和!-e用来判断是否存在文件或目录 \-x和!-x用来判断文件是否可执行 2、下面是可以用作判断的全局变量 $args #这个变量等于请求行中的参数。 $content\_length #请求头中的Content-length字段。 $content\_type #请求头中的Content-Type字段。 $document\_root #当前请求在root指令中指定的值。 $host #请求主机头字段,否则为服务器名称。 $http\_user\_agent #客户端agent信息 $http\_cookie #客户端cookie信息 $limit\_rate #这个变量可以限制连接速率。 $request\_body\_file #客户端请求主体信息的临时文件名。 $request\_method #客户端请求的动作,通常为GET或POST。 $remote\_addr #客户端的IP地址。 $remote\_port #客户端的端口。 $remote\_user #已经经过Auth Basic Module验证的用户名。 $request\_filename #当前请求的文件路径,由root或alias指令与URI请求生成。 $query\_string #与$args相同。 $scheme #HTTP方法(如http,https)。 $server\_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。 $server\_addr #服务器地址,在完成一次系统调用后可以确定这个值。 $server\_name #服务器名称。 $server\_port #请求到达服务器的端口号。 $request\_uri #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。 $uri #不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。 $document\_uri #与$uri相同。 例:http://localhost:88/test1/test2/test.php $host:localhost $server\_port:88 $request\_uri:http://localhost:88/test1/test2/test.php $document\_uri:/test1/test2/test.php $document\_root:D:\\nginx/html $request\_filename:D:\\nginx/html/test1/test2/test.php 四、Redirect语法 多目录转成参数 abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2 ~~~ if ($host ~* (.*)\.domain\.com) { set $sub_name $1; rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last; } ~~~ 目录对换 /123456/xxxx -> /xxxx?id=123456 1.     rewrite ^/(\\d+)/(.+)/ /$2?id=$1 last; 例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下: ~~~ if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; } ~~~ 目录自动加“/” ~~~ if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; } ~~~ 禁止htaccess ~~~ location ~/\.ht { deny all; } ~~~ 禁止多个目录 ~~~ location ~ ^/(cron|templates)/ { deny all; break;中止,不在继续匹配 } ~~~ 禁止以/data开头的文件 可以禁止/data/下多级目录下.log.txt等请求; ~~~ location ~ ^/data { deny all; } ~~~ 禁止单个目录 不能禁止.log.txt能请求 ~~~ location /searchword/cron/ { deny all; } ~~~ 禁止单个文件 ~~~ location ~ /data/sql/data.sql { deny all; } ~~~ 给favicon.ico和robots.txt设置过期时间; 这里为favicon.ico为99 天,robots.txt为7天并不记录404错误日志 ~~~ location ~(favicon.ico) { log_not_found off; expires 99d; break; } location ~(robots.txt) { log_not_found off; expires 7d; break; } ~~~ 设定某个文件的过期时间;这里为600秒,并不记录访问日志 ~~~ location ^~ /html/scripts/loadhead_1.js { access_log off; root /opt/lampp/htdocs/web; expires 600; break; } ~~~ 文件反盗链并设置过期时间 这里的return 412 为自定义的http状态码,默认为403,方便找出正确的盗链的请求 “rewrite ^/ http://leech.c1gstudio.com/leech.gif;”显示一张防盗链图片 “access\_log off;”不记录访问日志,减轻压力 “expires 3d”所有文件3天的浏览器缓存 ~~~ location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ { valid_referers none blocked *.c1gstudio.com *.c1gstudio.net localhost 208.97.167.194; if ($invalid_referer) { rewrite ^/ http://leech.c1gstudio.com/leech.gif; return 412; break; } access_log off; root /opt/lampp/htdocs/web; expires 3d; break; } ~~~ 只充许固定ip访问网站,并加上密码 ~~~ root /opt/htdocs/www; allow 208.97.167.194; allow 222.33.1.2; allow 231.152.49.4; deny all; auth_basic "C1G_ADMIN"; auth_basic_user_file htpasswd; ~~~ 将多级目录下的文件转成一个文件,增强seo效果 /job-123-456-789.html 指向/job/123/456/789.htm ~~~ rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last; ~~~ 将根目录下某个文件夹指向2级目录 如/shanghaijob/ 指向 /area/shanghai/ 如果你将last改成permanent,那么浏览器地址栏显是 /location/shanghai/ ~~~ rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last; ~~~ 上面例子有个问题是访问/shanghai 时将不会匹配 ~~~ rewrite ^/([0-9a-z]+)job$ /area/$1/ last; rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last; ~~~ 这样/shanghai 也可以访问了,但页面中的相对链接无法使用, 如./list\_1.html真实地址是/area /shanghia/list\_1.html会变成/list\_1.html,导至无法访问。 那我加上自动跳转也是不行咯 (-d $request\_filename)它有个条件是必需为真实目录,而我的rewrite不是的,所以没有效果 ~~~ if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; } ~~~ 知道原因后就好办了,让我手动跳转吧 ~~~ rewrite ^/([0-9a-z]+)job$ /$1job/ permanent; rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last; ~~~ 文件和目录不存在的时候重定向: ~~~ if (!-e $request_filename) { proxy_pass http://127.0.0.1; } ~~~ 域名跳转 ~~~ server { listen 80; server_name jump.c1gstudio.com; index index.html index.htm index.php; root /opt/lampp/htdocs/www; rewrite ^/ http://www.c1gstudio.com/; access_log off; } ~~~ 多域名转向 ~~~ server_name www.c1gstudio.com www.c1gstudio.net; index index.html index.htm index.php; root /opt/lampp/htdocs; if ($host ~ "c1gstudio\.net") { rewrite ^(.*) http://www.c1gstudio.com$1 permanent; } ~~~ 三级域名跳转 ~~~ if ($http_host ~* "^(.*)\.i\.c1gstudio\.com$") { rewrite ^(.*) http://top.yingjiesheng.com$1; break; } ~~~ 域名镜向 ~~~ server { listen 80; server_name mirror.c1gstudio.com; index index.html index.htm index.php; root /opt/lampp/htdocs/www; rewrite ^/(.*) http://www.c1gstudio.com/$1 last; access_log off; } ~~~ Nginx 服务器开启status页面检测服务状态开启后直接在浏览器的网站url地址后加上nginx_status 如:http://101.201.238.125:8080/nginx_status ~~~ #Nginx 服务器开启status页面检测服务状态 location /nginx_status { stub_status on; #并禁用了访问写入log文件 access_log off; #对访问者进行过滤 #allow 223.xxx.xxx.xxx; deny all; } ~~~