惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
O
OpenAI News
V
V2EX
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
小众软件
小众软件
L
LINUX DO - 热门话题
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - Franky
Security Latest
Security Latest
S
SegmentFault 最新的问题
Project Zero
Project Zero
Spread Privacy
Spread Privacy
K
Kaspersky official blog
J
Java Code Geeks
V
Vulnerabilities – Threatpost
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
月光博客
月光博客
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
人人都是产品经理
人人都是产品经理
博客园 - 三生石上(FineUI控件)
Scott Helme
Scott Helme
WordPress大学
WordPress大学
量子位
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Simon Willison's Weblog
Simon Willison's Weblog
S
Secure Thoughts
博客园 - 【当耐特】
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
V
Visual Studio Blog
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
腾讯CDC
Cyberwarzone
Cyberwarzone
IT之家
IT之家
GbyAI
GbyAI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
云风的 BLOG
云风的 BLOG
T
Troy Hunt's Blog
D
Docker

博客园 - oec2003

读《有效需求分析》 重读《打造 Facebook》 dotNet Core 3.1 使用 Aspose (部署 Docker) 为什么这么忙,还依然做不好事情? dotNET Core:编码规范 程序员是终身学习的职业,应该怎么学习? 一款用了就不想走的工具 dotNET:怎样处理程序中的异常(实战篇)? dotNET:怎样处理程序中的异常(理论篇)? 如何激发团队潜能? dotNET Core 3.X 使用 Autofac 来增强依赖注入 dotNET Core 3.X 依赖注入 读《鞋狗》 Jenkins 中以构建 Tag 来实现版本管理 dotNET Core 3.X 使用 Jwt 实现接口认证 dotNET Core 3.X 请求处理管道和中间件 dotNET Core 3.X 使用 Web API 程序员还有35岁的坎吗? 远程办公也可以高效
Nginx:rewrite 的几个技巧
oec2003 · 2020-07-06 · via 博客园 - oec2003

在软件的发布中,我们经常会使用到 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 移动端可以做解析实现直接登录

配置如下: