zoukankan      html  css  js  c++  java
  • 快速掌握Nginx(二) —— Nginx的Location和Rewrite

    1 location详解

    1.location匹配规则

      Nginx中location的作用是根据Url来决定怎么处理用户请求(转发请求给其他服务器处理或者查找本地文件进行处理)。location支持正则表达式,配置十分灵活。我们可以在一个虚拟主机(nginx中的一个server节点)下配置多个location以满足如动静分离,防盗链等需求。

      location语法是: location [=|~|~*|^~]  /uri/ {… },具体解释如下表:

    符号

    含义

    location  =    /url

    =   :开头,表示精确匹配,uri必须完全一致才能匹配成功

    location  ^~ /Purl

    ^~:Puri和请求url的开头相同就匹配成功,且不再去匹配正则,也属于普通匹配

    location        /Purl

    普通匹配,Purl和用户请求url的开头相同就匹配成功,如果有多个普通匹配都匹配成功则按最长的 。

      如有location /static/,和oaction /static/img/  当请求是www.mysite.com/static/img/1.jpg时,第二个location匹配的更长,所以和第二个loaction匹配成功。

    location   ~   reg

    ~  :区分大小写的正则匹配

    location  ~*  reg

    ~* :不区分大小写的正则匹配

    location的匹配顺序是: = /url   >   ^~ /Purl   > /Purl   >  ~ 和 ~* ,具体流程如下图所示,需要注意:一般情况下,匹配成功了普通字符串location后还会进行正则表达式location匹配。两种情况除外:①使用“=”,即精准匹配,如果匹配成功就立即停止其他匹配;②使用“^~”前缀,这个前缀告诉nginx ,如果匹配成功不再进行正则匹配。

    简单总结:

    1.  先进行精准匹配,如果匹配成功,立即返回结果并结束匹配过程。

    2.  进行普通匹配,如果有多个location匹配成功,将“最长前缀”的location作为临时结果(如果是 ^~类型的普通匹配成功则直接返回结果,结束匹配过程)。

    3.  由上至下逐一进行正则匹配,一旦匹配成功1个,立即返回结果,并结束解析过程;如果没有一个正则匹配成功,那么将普通匹配的最长前缀location作为最终结果返回,并结束匹配过程。

    2. 实际使用建议

    实际使用中,个人觉得每个虚拟主机下(server节点下)至少有三个匹配规则定义,如下:
    #直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
    #这里是直接转发给后端应用服务器了,也可以是一个静态首页
    # 第一个必选规则
    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/
    }

    实际使用建议参考自:https://segmentfault.com/a/1190000002797606

    2 rewrite详解

    1 rewrite简单认识

      rewrite模块即ngx_http_rewrite_module模块,主要功能是实现URI重定向。rewrite模块会通过正则匹配重写URI,然后内部跳转再匹配location,或者直接做30x重定向返回客户端。Nginx的rewrite功能需要PCRE的支持,PCRE是perl兼容正则表达式库。rewrite指令的语法十分简单如下:

     rewrite将符合正则的内容替换为新的替代内容
    rewrite <regex> <replacement>
    [flag]; 关键字 正则 替代内容 flag标记 正 则: perl兼容正则表达式语句进行规则匹配 替代内容: 将正则匹配的内容替换成replacement flag标记: rewrite支持的flag标记 ------------------------------------------------------------------------------- flag标记说明: last #匹配完成后不再匹配当前环境下的其他rewrite指令,开始匹配新的location URI规则 break #匹配完成即终止,不再匹配后面的任何规则 redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址 permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址

    使用rewrite时也会用到,几个常用的指令汇总如下:

    指令

    使用范围

    作用

    if ( condition ){ // 符合条件执行}

    location,server

    条件判断。

    =     !=  判断是否相等

    ~     ~* 判断是否符合正则

    -e    !-e 判断文件,目录,符号链接是否存在

    -d    !-d 判断目录是否存在

    -f     !-f 判断文件是否存在

    -x    !-x 判断是否可执行

    break

    server,location,if

    不再继续执行任何指令,直接退出规则的执行

    return 

    server,location,if

    结束规则的执行和返回状态码给客户端;如 return 403;

    set  variable  ‘value’

     http,server,location,if

     新建变量,并赋值 ;如 set varx 'hello'

      

       一个简单的栗子,简单了解下rewrite:

    server{
            listen 80;
            server_name www.mysite.com;
            #在server中调转到 爱奇艺
            #rewrite ^/(.*) https://www.iqiyi.com break;
            location = /{
                    #location中跳转到百度
                    rewrite ^/(.*) http://www.baidu.com;
                    root html;
                    index index.html;
            }
            #日志记录
            error_log logs/mysite.error.log error;
            access_log  logs/mysite.access.log  main;
    }       

      我们知道默认情况访问nginx的虚拟主机会展示nginx的欢迎界面,我们通过rewrite指令跳转到百度。输入虚拟机的IP,访问结果不再是nginx欢迎页,而是302跳转到百度如下:

     2 rewrite的执行过程

      nginx中我们可以有多个rewrite指令,默认情况下rewrite从上到下依次执行,并按最后一个匹配成功的作为最终结果。一种特殊情况是当replacement中包含http/https等协议名时,直接302跳转到replacement指定的url,不再执行后续的rewrite指令。
      那么如果我们想在执行一条rewrite指令后不再执行后续指令怎么办呢?这时就可以用rewrite中的flag标记,四种flag标记都可以实现不再往下执行其他rewrite指令的作用,但是每种flag标记的使用场景不同。介绍语法的时候已经介绍了四种flag的作用,我们来看一个栗子吧:
    server{
            listen 80;
            server_name www.mysite.com;
            location = /{
                    #跳转到百度
                    rewrite ^/(.*) http://www.baidu.com;
               #跳转到/test1
                    rewrite ^/(.*) /test1;
               #跳转到/test2
                    rewrite ^/(.*) /test2;
                    root html;
                    index index.html;
            }
            location /test1{
                    return 401;
            }
            location /test2{
                    return 402;
            }
    
            #日志记录
            error_log logs/mysite.error.log error;
            access_log  logs/mysite.access.log  main;
    }

      server进行上边的配置时,我们访问虚拟机IP 192.168.70.132,会跳转到百度页面,因为replacement包含了http协议名,不在执行后续的rewrite指令;

      如果把第一个rewrite注释掉,会调整到402错误页,因为rewrite的最终结果时以最后一个匹配成功的为准,最后匹配到 rewite /test2指令,然后找到location /test2返回402错误码;

      如果我们在rewrite  ^?(.*)  /test1后边加上last标记 ,表示不再匹配后边的rewrite,会跳到401错误页,url不变还是http://192.168.70.132;

      如果我们在rewrite  ^?(.*)  /test1后边加上redirect 或者 permanent 标记 ,表示不再匹配后边的rewrite,会跳转到401错误页(redirect的跳转码为302,permanet的跳转码时301),url会改变成 http://192.168.70.132/test1;

      如果我们在rewrite  ^?(.*)  /test1后边加上break标记 ,表示不再匹配任何规则,会跳转到404错误页;因为break标记不会再执行任何规则,所以不会再去找location test1,而是直接找 html/test1资源,所以出现404错误。

    3 一些常用的全局变量

      在使用rewrite指令时我们经常会用到一些常用的全局变量,这些全局变量定义在nginx/conf/fastcgi.conf中,列举如下:
     

    变量

    含义

    $args

    请求中的参数,同$query_string

    $content length

    请求头中的Content-length字段。

    $content_type

    请求头中的Content-Type字段。

    $document_root

    当前请求在root指令中指定的值。

    $host

    请求主机头字段,否则为服务器名称。

    $http_user_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,https)。

    $server_protocol

    请求使用的协议,通常是HTTP/1.0或HTTP/1.1。

    $server_addr

    服务器地址,在完成一次系统调用后可以确定这个值。

    $server_name

    服务器名称。

    $server_port

    请求到达服务器的端口号。

    $request_uri

    包含请求参数的原始URI,不包含主机名,如”/user/getuser?id=100”。

    $uri

    不带请求参数的当前URI,$uri不包含主机名,如”/user/getuser”。

    $document_uri

    与$uri相同。

    这里列举几个rewrite的简单栗子来帮助理解:

    ① 禁止特定IP访问
    server{
            listen 80;
            server_name localhost;
            location /{
            #如果客户端IP是192.168.70.1,那么拒接响应
               if ($remote_addr = 192.168.70.1){
                     return 403;
               }
               root html;
               index index.html;
            }
    }

      通过IP为192.168.70.1的电脑去访问时,结果如下:

    ② 根据浏览器不同跳转到不同页面
         #如果是google访问的,重定向到 html/chrome.html页面
            location /{
                    if ($http_user_agent ~ Chrome){
                            rewrite ^.*$  /chrome.html;
                            break;
                    }
                    root html;
                    index index.html;
            }

    ③ 文件不存在返回404,写的比较繁琐,主要是演示rewrite的用法

    server{
            listen 80;
            server_name www.mysite.com;
            location /{
            #如果文件不存在,跳转到notfound,
                    if (!-f  /usr/local/nginx/html/aaa.html){
                            rewrite ^/(.*) /notfound ;
                    }
                    root html;
                    index index.html;
            }
            location ~ /notfound {
                    return 404;
            }
            error_log logs/mysite.error.log error;
            access_log  logs/mysite.access.log  main;
    }

    小结:loaction和rewrite是nginx中最核心的指令,通过location和rewrite我们可以实现动静分离/规范客户端url等功能,因为支持perl的正则表达式,用法十分灵活。这里简单做了一些总结,如果有不正确的地方请指出。

    参考文章:

    【1】https://www.cnblogs.com/coder-yoyo/p/6346595.html

    【2】https://www.cnblogs.com/czlun/articles/7010604.html

    【3】https://www.cnblogs.com/crazylqy/p/6892010.html

     
     
    
    
    
  • 相关阅读:
    通用权限管理设计 之 数据库结构设计
    jQuery LigerUI 插件介绍及使用之ligerDateEditor
    jQuery LigerUI 插件介绍及使用之ligerTree
    jQuery LigerUI V1.01(包括API和全部源码) 发布
    jQuery liger ui ligerGrid 打造通用的分页排序查询表格(提供下载)
    jQuery LigerUI V1.1.5 (包括API和全部源码) 发布
    jQuery LigerUI 使用教程表格篇(1)
    jQuery LigerUI V1.0(包括API和全部源码) 发布
    jQuery LigerUI V1.1.0 (包括API和全部源码) 发布
    nginx keepalived
  • 原文地址:https://www.cnblogs.com/wyy1234/p/10632108.html
Copyright © 2011-2022 走看看