【Nginx快速扫盲】04史上最简单nginx规则|指令详解

写在前面,大家好!我是【跨考菌】,一枚跨界的程序猿,专注于后台技术的输出,目标成为全栈攻城狮!这博客是对我跨界过程的总结和思考。如果你也对Java后端技术感兴趣,抑或是正在纠结于跨界,都可以关注我的动态,让我们一起学习,一起进步~
我的博客地址为:【跨考菌】的博客

上一篇【Nginx快速扫盲】03 nginx高级功能极速入门 介绍了本文讲解nginx的高级功能。本文介绍nginx的常用规则和使用指令的详解。

在这里插入图片描述


1、location语法详解

1.1、语法说明

正则规则:

=开头表示精确匹配
^~ 开头表示uri以某个常规字符串开头,不是正则匹配【匹配之后,停止向下搜索】
/ 通用匹配, 如果没有其它匹配,任何请求都会匹配到
~ 区分大小写(大小写敏感)匹配成功
~* 不区分大小写匹配成功
!~ 区分大小写匹配失败
!~* 不区分大小写匹配失败

1.2、案例说明

现在有下面的一个匹配规则:

server {
	listen 80;
	server_name www.test138.com;
	
	error_log    /usr/local/nginx/test/data/logs/www.test138.com.error.log;
	
	
	location  = / {
	  # 精确匹配 / ,主机名后面不能带任何字符串
	  return 200 "[ configuration A ]"; 
	}
	 
	location  / {
	  # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
	  # 但是正则和最长字符串会优先匹配
	  return 200 "[ configuration B ] ";
	}
	 
	location /documents/ {
	  # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
	  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
	  return 200 "[ configuration C ] ";
	}
	 
	location ~ /documents/Abc {
	  # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
	  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
	  return 200 "[ configuration CC ] ";
	}

	
	location ^~ /images/ {
	  # 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
	  return 200 "[ configuration D ] ";
	}
	 
	location ~* \.(gif|jpg|jpeg)$ {
	  # 匹配所有以 gif,jpg或jpeg 结尾的请求
	  # 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则
	  return 200 "[ configuration E ] ";
	}

	location /images/abc {
	  # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
	  # F与G的放置顺序是没有关系的
	  return 200 "[ configuration G ] ";
	}
	 
	location ~ /images/abc/ {
	  # 只有去掉 config D 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用
		return 200 "[ configuration H ] ";
	}
	 
	location ~* /js/.*/\.js {
		return 200 "[I]";
	}
   } 	

产生的效果为:

  • 访问http://www.test138.com/,匹配到A
  • 访问http://www.test138.com/hello,匹配到B【其他的都没匹配】
  • 访问http://www.test138.com/documents/hello,匹配到C【往下搜索没有找到匹配的】
  • 访问http://www.test138.com/documents/Adc/hello,匹配到CC
  • 访问http://www.test138.com/images/hello,匹配到D
  • 访问http://www.test138.com/a.jpg,匹配到E
  • 访问http://www.test138.com/images/a.jpg,匹配到D
  • 访问http://www.test138.com/images/abc,匹配到G

顺序和优先级:

( location = ) > ( location 完整路径 ) > ( location ^~ 路径 ) > ( location ,* 正则顺序 ) > ( location 部分起始路径 ) > ( / )

2、实际使用的建议

三点规则匹配的总结:

#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则!!!!!!!!!!!!!!
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/
}

3、nginx中的root和alias的区别

nginx指定文件路径有两种方式root和alias,这两者的用法区别,使用方法总结了下,方便大家在应用过程中,快速响应。root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。

[root]
语法:root path
默认值:root html
配置段:http、server、location、if
[alias]
语法:alias path
配置段:location

①、root用法案例

我的ip地址为:192.168.229.134

 location ^~ /t/ {
            root /usr/local/nginx/test/data/www/134/;
        }

在这里插入图片描述

如果一个请求的URI是/t/a.html时,web服务器将会返回服务器上的/usr/local/nginx/test/data/www/134 /t/a.html 的文件。

②、alias用法案例

location ^~ /m/ {
            alias /usr/local/nginx/test/data/www/134/;
        }

如果一个请求的URI是/m/hello.html时,web服务器将会返回服务器上的/usr/local/nginx/test/data/www/134 /hello.html的文件。注意这里是不需要/m,因为alias会把location后面配置的路径丢弃掉,把当前匹配到的目录指向到指定的目录。

注意:

  1. 使用alias时,目录名后面一定要加"/"。
  2. alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。
  3. alias只能位于location块中。(root可以不放在location中)

4、rewrite

4.1、rewrite介绍

Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。
配置语法为:

rewrite regex replacement [flag]

使用案例:

location / {
	rewrite ^/ https://www.baidu.com;  # 所用请求都重定向到baidu去。
}

rewrite只能放在server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用。
Rewrite主要的功能就是实现URL的重写,Nginx的Rewrite规则采用Pcre,perl兼容正则表达式的语法规则匹配,如果需要Nginx的Rewrite功能,在编译Nginx之前,需要编译安装PCRE库。
通过Rewrite规则,可以实现规范的URL、根据变量来做URL转向及选择配置。

rewrite和location的功能有点相像,都能实现跳转,主要区别在于rewrite常用于同一域名内更改获取资源的路径,而location是对一类路径做控制访问和反向代理,可以proxy_pass到其他服务器

他们的执行顺序为:

执行server块的rewrite指令
执行location匹配
执行选定的location中的rewrite指令

4.2、四种Flag

  • last 停止处理后续rewrite指令集,跳出location作用域,并开始搜索与更改后的URI相匹配的location,URL地址不变

  • break 停止处理后续rewrite指令集,不会跳出location作用域,不再进行重新查找,终止匹配,URL地址不变

  • redirect 返回302临时重定向,浏览器地址栏会显示跳转后的URL地址,爬虫不会更新自己的URL数据库

  • permanent 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址,爬虫会更新自己的URL数据库

注:使用last和break时浏览器中的地址不会改变,使用redirect和permanent则会改变

案例:

location /abc/ {
  rewrite ^/abc/(.*) /whsir/$1 break;
  return 401;
}
location /opq/ {
  rewrite ^/opq/(.*) /whsir/$1 last;
  return 402;
}

location /gpr/ {
   rewrite ^/abc/(.*) /whsir/$1 redirect;
   return 405;
}

location /mnt/ {
   rewrite ^/opq/(.*) /whsir/$1 permanent;
   return 406;
}

location /whsir/ {
  return 403;
}
  • 访问http://www.test135.com/abc/,返回404【因为break不会跳出location且会终止rewrite指令集】
  • 访问http://www.test135.com/opq/,返回403【因为last会跳出location且跳出rewrite指令集,最终达到了/whsir/路径继续匹配】
  • 访问http://www.test135.com/gpr/,返回403【浏览器url变化】
  • 访问http://www.test135.com/mnt/,返回403【浏览器url变化】

4.3、使用案例

①、将http跳转到https

server {
	listen 80;
	server_name www.test.com;
	rewrite ^(.*) https://$request_uri redirect;
	# return 302 https://$request_uri; # 第二种方式
}

server {
	listen 443;
	server_name www.test.com;
	ssl on; # nginx1.14版本之后不用写ssl on了,listen哪些协程listen 443 ssl;

②、将www.test.com/2020/* 重定向到 www.test.com/2019/

location /2020 {
	rewite ^/2020/(.*)$ /2019/$1 redirect;

③、案例3

http {
    # 定义image日志格式
    log_format imagelog '[$time_local] ' $image_file ' ' $image_type ' ' $body_bytes_sent ' ' $status;
    # 开启重写日志
    rewrite_log on;
 
    server {
        root /home/www;
	server_name www.test135.com;
 
        location / {
                # 重写规则信息
                error_log /usr/local/nginx/test/data/logs/www.test135.com.error.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 /usr/local/nginx/test/data/logs/images.log;
                root /usr/local/nginx/test/data/images;
                # 应用前面定义的变量。判断首先文件在不在,不在再判断目录在不在,如果还不在就跳转到最后一个url里
                try_files /$arg_file /image404.html;
        }
        location = /image404.html {
                # 图片不存在返回特定的信息
                return 404 "image not found\n";
        }
    }
}

测试:

访问http://www.test135.com/images/ef/uh7b3/test.png的请求,重定向到/date?file=test.png,于是匹配到location /data,先看/usr/local/nginx/test/data/images/test.png文件是否存在,如果存在则正常响应,如果不存在则重写tryfiles到新的image404 location,直接返回404状态码。分别对应下面两种情况:

在这里插入图片描述

在这里插入图片描述

④、案例4

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。

5、全局变量

常用的全局变量如下:

$args : #这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$document_root : 当前请求在root指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$limit_rate : 这个变量可以限制连接速率。
$request_method : 客户端请求的动作,通常为GET或POST。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$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:8080/test1/test2/test.html
$host:localhost
$server_port:8080
$request_uri:http://localhost:8080/test1/test2/test.html
$document_uri:/test1/test2/test.html
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.html

6、正则

. : 匹配除换行符以外的任意字符
? : 重复0次或1+ : 重复1次或更多次
* : 重复0次或更多次
\d :匹配数字
^ : 匹配字符串的开始
$ : 匹配字符串的结束
{n} : 重复n次
{n,} : 重复n次或更多次
[c] : 匹配单个字符c
[a-z] : 匹配a-z小写字母的任意一个

小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。正则里面容易让人困惑的是\转义特殊字符。

7、判断指令

语法为if(condition){…},对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:

当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
直接比较变量和内容时,使用=!=
~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行

举例:

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite请求到/msid/目录下
 
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
 } //如果cookie匹配正则,设置变量$id等于正则引用部分
 
if ($request_method = POST) {
    return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
 
if ($slow) {
    limit_rate 10k;
} //限速,$slow可以通过 set 指令设置
 
if (!-f $request_filename){
    break;
    proxy_pass  http://127.0.0.1; 
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
 
if ($args ~ post=140){
    rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
 
location ~* \.(gif|jpg|png|swf|flv)$ {
    valid_referers none blocked www.jefflei.com www.leizhenfang.com;
    if ($invalid_referer) {
        return 404;
    } //防盗链
}

8、break指令

server {
        listen 80;
        server_name www.test136.com; # 配置的域名
        # break && rewrite test 
        # 这里如果注释掉了break,所有请求进来都是返回200,this is breaktest...
        break;
        return 200 "this is breaktest...";
        location = /breaktest {
            break;
            return 200 $request_uri;
            proxy_pass http://www.test136.com/other;
        }
        location / {
            return 200 $request_uri;
        }
    }

访问:http://www.test136.com/breaktest

运行结果说明:
测试链接:http://www.test136.com/breaktest ,请求到达server块后,被break终止执行rewrite指令集,return属于rewrite模块指令集,所以return 200 “this is breaktest…”不会执行;因为没有返回结果,所以继续执行location匹配,请求匹配到location = /breaktest{}之后,break终止return 200 $request_uri,而proxy_pass属于ngx_http_proxy_module,仍会继续执行,反向代理后的新url匹配到location /{},因此最终返回结果为 http200,/other,如下图:

在这里插入图片描述

9、set指令

server {
        listen 80;
        server_name www.test137.com;
        # break && rewrite test 
        # 这里如果注释掉了break,所有请求进来都是返回200,this is breaktest...
        break;
        return 200 "this is breaktest...";
        location = /breaktest {
            break;
            return 200 $request_uri;
            proxy_pass http://www.test137.com/other;
        }
        location / {
            # set赋值,可以直接赋字符串或者变量,如下是变量和字符串的组合
            set $set_value_test "112233 $request_uri";
            return 200 $set_value_test;
        }
    }

访问:http://www.test136.com/breaktest
在这里插入图片描述

在这里插入图片描述

如果你觉得对您有帮助,不要忘记帮博主一键三连😊哦

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值