• Nginx:rewrite 的几个技巧


    在软件的发布中,我们经常会使用到 Nginx,Nginx 的功能非常的庞杂,其中 rewrite 是一个非常常用的功能模块,本文介绍 rewrite 的基本概念和几个小技巧。

    rewrite 是 Nginx 中的一个模块,这个模块用来重定向页面,在 rewrite 模块中包含了几个指令来实现不同的功能:

    • return
    • rewrite
    • if

    return 指令

    return 指令是 rewrite 模块中非常常用的一个指令,可以帮助我们做重定向和一些简单的返回。

    语法

    return code text;
    return code URL;
    return URL;
    

    return 指令的语法由两个或三个部分组成:

    • return: 关键字
    • code:http 状态码,当没有设置 code 时,默认使用 302
    • text 或 URL:返回的字符串或跳转的地址

    使用范围

    • server 节点
    • location 节点
    • if 块中

    • 在 server 节点中的 return 的优先级要高于 location 节点的 return,不管 return 指令写在 location 节点的上方还是下方
    • 在 return 指令中使用 code,经常会用到 301 或 302 ,区别如下:
      • 301:永久重定向,例如访问 a.com,通过 return 使用 301 重定向到了 b.com,然后修改 return 的地址为 c.com,访问 a.com,还是访问的 b.com,因为被缓存了
      • 302:临时重定向,例如访问 a.com,通过 return 使用 302 重定向到了 b.com,然后修改 return 的地址为 c.com,访问 a.com,会跳转到 c.com,不会被缓存

    rewrite 指令

    可以根据指定的正则表达式将用户请求的 url 转换成一个新的 url 进行重定向。

    语法

    rewrite regex replacement [flag];
    

    return 指令的语法四个部分组成:

    • rewrite: 关键字
    • regex:正则表达式,用于匹配用户请求的 url 地址
    • replacement:新的 url 地址,当地址开头为 http 或 https ,默认为 302 重定向
    • flag:替换后的 url 根据 flag 进行处理,flag 有四个值
      • last:使用 replacement 的地址重新进行 location 匹配
      • break:会停止后面脚本的执行
      • redirect:返回 302 重定向,地址栏显示重定向后的url
      • permanent:返回 301 重定向,地址栏显示重定向后的url

    使用范围

    • server 节点
    • location 节点
    • if 块中

    • rewrite 指令的适用范围和 return 指令的是一致的,优先级也相同
    • 当 rewrite 指令和 return 指令同时存在时,如果 rewrite 最后的 flag 不是 break,会继续执行 rewrite 之后的 return 指令
    • 没有指定 flag 的情况下,默认为 302 重定向

    if 指令

    通过 if 指令进行一些条件的判断,然后进行 return、rewrite 或是其他的一些处理。

    语法

    if(condition){
    }
    

    使用范围

    • server 节点
    • location 节点

    if 判断的一些规则

    • 变量和字符串做比较,使用 = 或 !=
    • 将变量和正则表达式做比较:
      • 大小写敏感:~ 或 !~
      • 大小写不敏感:~* 或 !~* ,例如上图中的示例
    • 检查文件是否存在,使用 -f 或 !-f
    • 检查目录是否存在,使用 -d 或 !-d

    示例

    下面以近期用到的两个场景来演示实际的用法。

    PC 端跳转到移动端

    场景描述:

    • PC 端发布后的地址为:192.168.0.1
    • 移动端采用 H5 开发,发布后的地址:192.168.0.1:81
    • 在手机上访问 PC 端地址,跳转到移动端
    • PC 端和移动端使用同一个接口地址,接口地址是在 PC 端使用 /api 进行的代理
    • 只有页面的请求跳转到移动端,接口的请求不需要跳转

    配置如下:

    server {
        listen       80;
        server_name  localhost;
    
        set $flag 0;
    
        if ($http_user_agent ~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry) ) {
          set $flag "${flag}1";
        }
    
        if ($request_uri !~* /api/) {
          set $flag "${flag}2";
        }
    
        if ($flag = "012") {
           rewrite  ^(.*)    http://192.168.0.1:81? permanent;
        }
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    
        location /api/ {
          proxy_pass http://192.168.0.1:5000/;
        }
    
        error_page   500 502 503 504  /50x.html;
    }
    
    • 两个条件都满足的情况下,进行跳转
      • 设备类型为移动端
      • 请求的路由中不包含 /api
    • 因为 if 指令的条件的限制,不能再一个 condition 中使用多条件,所以定义了一个变量 $flag 来做判断

    将源地址中的特定参数传递到目标地址

    场景描述:

    • 上面的示例中,跳转到移动端后进入的是移动端的登录页面,因为没有登录人的身份
    • 现在假设 PC 端的地址后有 authcode 的参数用来确定身份,除此之外还有其他的参数,例如:http://192.168.0.1?id=xxxxx&authcode=xxxxxxxx
    • 需要再跳转后将 authcode 传递到移动端的地址后面,例如:http://192.168.0.1:81?authcode=xxxxxxxx 移动端可以做解析实现直接登录

    配置如下:

  • 相关阅读:
    哨兵模式(工作中使用)
    JVM调优-考虑方向
    Spring Cloud Gateway+Nacos出现服务乱串的问题记录
    golang笔记-cache组件应用: freecache/groupcache/golang-lru
    C++优化笔记: -O2/-O3/-ffast-math/SIMD
    linux笔记-查看L1/L2/L3 cache大小
    Dom4j 如何输出 Document 中的内容到文本
    是应该是用 Log 还是 Logger 来定义 Log
    IntelliJ IDEA 如何针对Java 代码快速打印 println
    如何用 Java 判断一个给定的数是不是素数
  • 原文地址:https://www.cnblogs.com/oec2003/p/13929257.html
Copyright © 2020-2023  润新知