从零手写实现 nginx-23-directive IF 条件判断指令
前言
大家好,我是老马。很高兴遇到你。
我们为 java 开发者实现了 java 版本的 nginx
https://github.com/houbb/nginx4j
如果你想知道 servlet 如何处理的,可以参考我的另一个项目:
手写从零实现简易版 tomcat minicat
手写 nginx 系列
如果你对 nginx 原理感兴趣,可以阅读:
从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?
从零手写实现 nginx-02-nginx 的核心能力
从零手写实现 nginx-03-nginx 基于 Netty 实现
从零手写实现 nginx-04-基于 netty http 出入参优化处理
从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)
从零手写实现 nginx-06-文件夹自动索引
从零手写实现 nginx-07-大文件下载
从零手写实现 nginx-08-范围查询
从零手写实现 nginx-09-文件压缩
从零手写实现 nginx-10-sendfile 零拷贝
从零手写实现 nginx-11-file+range 合并
从零手写实现 nginx-12-keep-alive 连接复用
从零手写实现 nginx-13-nginx.conf 配置文件介绍
从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?
从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?
从零手写实现 nginx-16-nginx 支持配置多个 server
从零手写实现 nginx-17-nginx 默认配置优化
从零手写实现 nginx-18-nginx 请求头+响应头操作
从零手写实现 nginx-19-nginx cors
从零手写实现 nginx-20-nginx 占位符 placeholder
前言
大家好,我是老马。
这一节我们将配置的加载,拆分为不同的模块加载处理,便于后续拓展。
if
详细介绍一下 nginx 的 if 指令
Nginx 的 if 指令是一个用来在配置文件中进行条件判断的工具。
它通常用于 server、location、和 http 块中,用于执行特定的指令或改变请求的处理方式。
虽然它提供了灵活性,但也需要小心使用,因为某些情况下它可能会导致配置复杂化或带来意想不到的行为。
语法
if (condition) {# 指令
}
常见条件判断
变量值匹配:
if ($variable = value) {# 指令 }变量值不匹配:
if ($variable != value) {# 指令 }变量是否设置:
if ($variable) {# 指令 }变量是否为空:
if ($variable = "") {# 指令 }正则表达式匹配:
if ($variable ~ pattern) {# 指令 }正则表达式不匹配:
if ($variable !~ pattern) {# 指令 }正则表达式匹配并忽略大小写:
if ($variable ~* pattern) {# 指令 }正则表达式不匹配并忽略大小写:
if ($variable !~* pattern) {# 指令 }
示例
重定向非 www 的请求到 www:
server {server_name example.com;if ($host = example.com) {return 301 http://www.example.com$request_uri;} }基于 User-Agent 的条件处理:
location / {if ($http_user_agent ~* "MSIE") {return 403;}# 其他指令 }阻止某个特定 IP 访问:
location / {if ($remote_addr = 192.168.1.1) {return 403;}# 其他指令 }
注意事项
if指令的限制:if指令在某些情况下可能会导致配置难以维护,特别是在嵌套复杂逻辑时。- 它不能改变现有上下文中的配置(如
server或location),只能对请求进行处理。
避免使用
if进行重写逻辑: Nginx 官方推荐尽量使用map指令、重写模块 (rewrite) 等替代if指令来处理 URL 重写等操作,因为这些方法更高效且更直观。尽量使用
try_files: 在处理静态文件和重定向时,try_files是一个更好的选择,因为它在性能和可读性上更优。
更好的选择
在某些情况下,使用 map 指令或者特定模块(如 rewrite 模块)可以替代 if 指令,提供更高效且清晰的配置。
例如,可以使用 map 指令来处理复杂的条件逻辑:
map $host $is_www {default 0;"www.example.com" 1;"example.com" 2;
}server {server_name example.com www.example.com;if ($is_www = 2) {return 301 http://www.example.com$request_uri;}
}
总结来说,Nginx 的 if 指令可以用于条件判断,但在使用时应谨慎,尽量考虑其他更高效和可维护的替代方案。
nginx if 模块,放在 http 模块,server 模块,location 块中的配置例子
下面是一些 Nginx 配置示例,展示如何在 http、server 和 location 模块中使用 if 指令。
每个示例都会说明如何在这些不同的上下文中使用 if 指令来进行各种条件判断。
在 http 模块中使用 if 指令
http {# 示例变量set $example_variable "test_value";# 变量值匹配if ($example_variable = "test_value") {# 执行指令,例如设置另一个变量set $matched "yes";}# 变量是否设置if ($example_variable) {# 执行指令,例如设置另一个变量set $is_set "yes";}# 其他 HTTP 块配置server {listen 80;server_name example.com;location / {root /var/www/html;index index.html;}}
}
在 server 模块中使用 if 指令
http {server {listen 80;server_name example.com;# 示例变量set $example_variable "test_value";# 变量值不匹配if ($example_variable != "other_value") {# 执行指令,例如重定向return 301 http://example.com/redirect;}# 变量是否为空if ($example_variable = "") {# 执行指令,例如返回 404return 404;}location / {root /var/www/html;index index.html;}}
}
在 location 模块中使用 if 指令
http {server {listen 80;server_name example.com;location / {root /var/www/html;index index.html;# 示例变量set $example_variable "test_value";# 正则表达式匹配if ($example_variable ~ "^test.*") {# 执行指令,例如设置头部add_header X-Matched "yes";}# 正则表达式匹配并忽略大小写if ($example_variable ~* "TEST.*") {# 执行指令,例如设置头部add_header X-Matched-IgnoreCase "yes";}# 正则表达式不匹配if ($example_variable !~ "^no_match$") {# 执行指令,例如返回 403return 403;}}}
}
配置说明
在
http模块中:这里的if指令可以用来设置全局变量或根据条件设置变量。配置项适用于整个http块中的所有server和location。在
server模块中:if指令用于服务器级别的配置,例如条件重定向或返回特定的 HTTP 状态码。在
location模块中:if指令可以针对特定的 URL 路径进行更细粒度的控制,如条件设置响应头部或根据变量值返回特定状态码。
请注意,虽然在 if 指令中可以执行很多操作,但在实际配置中应尽量避免过于复杂的逻辑,以确保服务器的高性能和可维护性。如果有更复杂的需求,建议考虑使用 Nginx 的 map 指令或其他更合适的模块。
java 如何实现 nginx 的 if 指令特性(基础能力)
一些思考
感觉我们需要把配置文件中的基础属性全部全拿出来?不然初始化的时机要怎么定义呢?
IF 指令也应该是在根据最新的数据,条件判断得到的。
核心实现
/*** 操作符** @since 0.21.0* @author 老马啸西风*/
public class NginxIfOperatorManager {private static final Map<String, NginxIfOperator> map = new HashMap<>();static {final NginxIfOperatorDefine operatorDefine = new NginxIfOperatorDefine();final NginxIfOperatorEquals operatorEquals = new NginxIfOperatorEquals();final NginxIfOperatorNotEquals operatorNotEquals = new NginxIfOperatorNotEquals();final NginxIfOperatorRegexMatch regexMatch = new NginxIfOperatorRegexMatch();final NginxIfOperatorRegexNotMatch regexNotMatch = new NginxIfOperatorRegexNotMatch();final NginxIfOperatorRegexMatchIgnoreCase regexMatchIgnoreCase = new NginxIfOperatorRegexMatchIgnoreCase();final NginxIfOperatorRegexMatchIgnoreCaseNot regexMatchIgnoreCaseNot = new NginxIfOperatorRegexMatchIgnoreCaseNot();map.put(operatorDefine.operator(), operatorDefine);map.put(operatorEquals.operator(), operatorEquals);map.put(operatorNotEquals.operator(), operatorNotEquals);map.put(regexMatch.operator(), regexMatch);map.put(regexNotMatch.operator(), regexNotMatch);map.put(regexMatchIgnoreCase.operator(), regexMatchIgnoreCase);map.put(regexMatchIgnoreCaseNot.operator(), regexMatchIgnoreCaseNot);}public boolean match(NginxCommonConfigEntry configParam, NginxRequestDispatchContext dispatchContext) {List<String> values = configParam.getValues();String key = getOperKey(configParam, dispatchContext);return map.get(key).eval(values.get(0), values.get(2), dispatchContext);}protected String getOperKey(NginxCommonConfigEntry configParam, NginxRequestDispatchContext dispatchContext) {List<String> values = configParam.getValues();if(values.size() == 1) {return "";}return values.get(1);}}
小结
if 是一个非常灵活的能力,但是非常灵活的同时,可能会导致配置变得难以维护。
我们后续考虑继续学习下 map rewrite try_files 等指令。
我是老马,期待与你的下次重逢。
开源地址
为了便于大家学习,已经将 nginx 开源
https://github.com/houbb/nginx4j
相关文章:
从零手写实现 nginx-23-directive IF 条件判断指令
前言 大家好,我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的,可以参考我的另一个项目: 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …...
08_基于GAN实现人脸图像超分辨率重建实战_超分辨基础理论
1. 超分辨的概念与应用 我们常说的图像分辨率指的是图像长边像素数与图像短边像素数的乘积,比如iPhoneX手机拍摄照片的分辨率为 4032px3024px,为1200万像素。 显然,越高的分辨率能获得更清晰的成像。与之同时,分辨率越高也意味着更大的存储空间,对于空间非常有限的移动设…...
React.ReactElement 与 React.ReactNode
React.ReactNode 在 JSX 中作为子元素传递的所有可能类型的并集,这是对子元素的一个非常宽泛的定义。 <RNode><p>One element</p></RNode><RNode><><p>Fragments for</p><p>More elements</p></&g…...
深度解析服务发布策略之蓝绿发布
目录 什么是蓝绿发布 蓝绿发布的优点 蓝绿发布的缺点 蓝绿发布的实现步骤 小结 在软件开发和运维中,发布新版本是一个风险较高的操作。为了降低风险,提高发布的稳定性和可靠性,通常会采取一系列的技术策略。其中蓝绿发布(Blu…...
【Mysql】 深入理解MySQL的执行计划
文章目录 前言一、字段解释二、代码实现三、总结 前言 在日常的数据库操作中,我们经常会遇到一些复杂的查询,这些查询可能会涉及到多个表的联合查询,或者是一些复杂的条件筛选。为了更好地理解和优化这些查询,了解MySQL的执行计划…...
说下你对Spring IOC 的理解
说下你对Spring IOC 的理解 1. Spring IOC是一个管理对象之间依赖关系的容器,它实现了依赖注入技术,可以解决传统的紧耦合问题,降低了项目维护难度。 2. Spring IOC将对象之间的依赖关系交由容器来管理对象,开发者只需要告诉容器…...
前缀和算法:算法秘籍下的数据预言家
✨✨✨学习的道路很枯燥,希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一. 前缀和算法的介绍 二、前缀和例题 2.1 【模版】前缀和 2.2 【模板】二维前缀和 2.3 寻找数组的中间下标 2.4 除自身以外数组的乘积 2.5 和为k的子数组 2.6 和可被k整除的子数组 2.7 …...
基于PointNet / PointNet++深度学习模型的激光点云语义分割
一、场景要素语义分割部分的文献阅读笔记 1.1 PointNet PointNet网络模型开创性地实现了直接将点云数据作为输入的高效深度学习方法(端到端学习)。最大池化层、全局信息聚合结构以及联合对齐结构是该网络模型的三大关键模块,最大池化层解决了…...
LabVIEW调用DLL时需注意的问题
在LabVIEW中调用DLL(动态链接库)是实现与外部代码集成的一种强大方式,但也存在一些常见的陷阱和复杂性。本文将从参数传递、数据类型匹配、内存管理、线程安全、调试和错误处理等多个角度详细介绍LabVIEW调用DLL时需要注意的问题,…...
时序预测 | MATLAB实现TCN-Attention自注意力机制结合时间卷积神经网络时间序列预测
时序预测 | MATLAB实现TCN-Attention自注意力机制结合时间卷积神经网络时间序列预测 目录 时序预测 | MATLAB实现TCN-Attention自注意力机制结合时间卷积神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现TCN-Attention自注意力机制结合时…...
上位机图像处理和嵌入式模块部署(h750 mcu vs f407)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在目前工业控制上面,f103和f407是用的最多的两种stm32 mcu。前者频率低一点,功能少一点,一般用在低端的嵌入式设…...
Linux C语言:指针和指针变量
一、指针的作用 使程序简洁、紧凑、高效有效地表示复杂的数据结构动态分配内存能直接访问硬件能够方便的处理字符串得到多于一个的函数返回值 二、内存、地址和变量 1、内存地址 2、变量和地址 1)变量用来在程序中保存数据 比如: int k 58; //声明一个int变…...
Llama模型家族之Stanford NLP ReFT源代码探索 (二)Intervention Layers层
LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (三) 基于 LlaMA…...
MATLAB神经网络---序列输入层sequenceInputLayer
序列输入层sequenceInputLayer 描述一: sequenceinputlayer是Matlab深度学习工具箱中的一个层,用于处理序列数据输入。它可以将输入数据转换为序列格式,并将其传递给下一层进行处理。该层通常用于处理文本、语音、时间序列等类型的数据。在使用该层时&…...
使用CSS、JavaScript、jQuery三种方式实现手风琴效果
手风琴效果有不少,王者荣耀官网(源网址 https://pvp.qq.com/raiders/ )有一处周免英雄,使用的就是手风琴效果,如图所示。 我试着用css、js、jQuery三种方式实现了这种效果,最终效果差不多,美中不…...
什么是无头浏览器以及其工作原理?
如果您对这个概念还不熟悉,那么使用无头网络浏览器的想法可能会让您感到不知所措。无头浏览器本质上与您熟悉的网络浏览器相同,但有一个关键区别:它们没有图形用户界面 (GUI)。这意味着没有按钮、选项卡、地址栏或视觉显示。 相反,…...
计算机网络 —— 应用层(DNS域名系统)
计算机网络 —— 应用层(DNS域名系统) 什么是DNS域名的层次结构域名分类 域名服务器的分类域名解析方式递归查询(Recursive Query)迭代查询(Iterative Query)域名的高速缓存 我们今天来看DNS域名系统 什么…...
Linux--MQTT简介
一、简介 MQTT ( Message Queuing Telemetry Transport,消息队列遥测传输), 是一种基于客户端服务端架构的发布/订阅模式的消息传输协议。 与 HTTP 协议一样, MQTT 协议也是应用层协议,工作在 TCP/IP 四…...
VMware Workerstation开启虚拟机后,产生乱码名称日志文件
问题情况 如下图所示,我的虚拟机版本是16.1.2版本,每次在启动虚拟机之后,D盘目录下都会产生一个如图下所示的乱码名称文件。同时,虚拟机文件目录也是杂乱不堪,没有按照一台虚拟机对应一个文件夹的形式存在。 问题处理…...
Unity射击游戏开发教程:(27)创建带有百分比的状态栏
创建带有弹药数和推进器百分比的状态栏 在本文中,我将介绍如何创建带有分数和百分比文本的常规状态栏。 由于 Ammo Bar 将成为 UI 的一部分,因此我们需要向 Canvas 添加一个空的 GameObject 并将其重命名为 AmmoBar。我们需要一个文本和两个图像对象,它们是 AmmoBar 的父级。…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
