从零手写实现 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 的父级。…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...
