ngx_http_test_expect
1 定义ngx_http_test_expect 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_request_body.c2 目的HTTP 协议中的 Expect 头部 HTTP 请求由“请求头部”和可选的“请求体”组成。 请求头部里可以包含一个字段叫 Expect。 Expect 字段的作用是 客户端在真正发送请求体之前告诉服务器 “我期望你满足某个条件如果你能满足我再把请求体发过去 如果你不能满足就立刻告诉我我就不发请求体了免得浪费带宽和时间。” 最常见的用法就是 Expect: 100-continue。 它的工作流程分两步 客户端发送请求头部 其中包含 Expect: 100-continue 然后暂停等待服务器回应。此时客户端还没有发送请求体。 服务器收到这些头部后检查请求。如果服务器愿意接收请求体 就立刻发送一个临时响应 100 Continue。 客户端收到这个 100 Continue 后才开始发送请求体。 如果服务器不愿意接收比如权限不足、文件太大 服务器可以直接返回一个错误状态码比如 403 或 413 然后连接终止或忽略请求体客户端就不会再发送无用的请求体了。 这是一种优化机制特别适用于大的请求体。 如果服务器一看请求头部就决定拒绝就可以省去传输整个请求体的时间和资源。设计 ngx_http_test_expect 的核心目的 这个函数就是 Nginx 用来实现上面第 2 步中“服务器端的检查和回应”的。 具体来说它的任务是 检查当前请求是否带有 Expect: 100-continue 头部 并且是否满足需要处理的条件HTTP 版本、未测试过等。 响应如果确认客户端在期待一个 100 Continue 回应 就立即向客户端发送这个回应告诉客户端“你可以继续发送请求体了”。 记录状态 标记这个请求的 Expect 头部已经测试过防止重复发送 100 Continue。为什么需要把它设计成一个单独的函数 因为在 Nginx 中有多个地方可能需要触发这个“测试-回应”的动作。 因此它被封装成一个独立的函数供各处使用。3 详解1 函数签名staticngx_int_tngx_http_test_expect(ngx_http_request_t*r)1. 返回值类型ngx_int_t这个函数的返回值不是实际的业务数据而是一个状态码用来表示函数执行的结果。可能的返回值有NGX_OK处理成功这可能包括“不需要做任何事”的情况例如请求没有 Expect 头部或者成功发送了 100 Continue 响应。NGX_ERROR处理失败例如发送 100 Continue 响应时发生网络错误。调用者会根据这个返回值决定后续处理是正常继续还是向上传递错误。2. 函数名ngx_http_test_expect函数名由多个部分用下划线连接遵循 Nginx 的命名惯例ngx全局前缀表明这是 Nginx 源码的一部分。http表明该函数属于 HTTP 核心模块处理 HTTP 协议相关的逻辑。test动词意思是“测试、检查”。在这里指检查请求的 Expect 头部。expect直接对应 HTTP 协议中的 Expect 请求头部。整体名字的含义是在 HTTP 模块中测试并处理Expect 请求头部的函数。这个名字精确概括了它的功能。3.ngx_http_request_t *r参数 r是一个指针指向代表当前 HTTP 请求的结构体里面包含了所有相关的信息。2 逻辑流程1 检查 过滤无需发送 100 Continue 的情况直接返回 NGX_OK 1-1 如果请求已经测试过 或根本没有 Expect 头部 或 HTTP 版本低于 1.1 或这是 HTTP/2 请求 则直接返回 NGX_OK不做任何事。 1-2 设置 expect_tested 标志为 1防止重复处理。 1-3 获取 Expect 头部的值。 如果该值不是 100-continue长度不同或内容不匹配则忽略它返回 NGX_OK。 2 发送 100 Continue 2-1 否则发送 HTTP/1.1 100 Continue\r\n\r\n 到客户端。 2-2 如果发送完整返回 NGX_OK 2-3 否则标记连接错误返回 NGX_ERROR。 这个函数的核心意义在于 正确实现 HTTP/1.1 的 Expect: 100-continue 协议 并提供一个可被多个地方调用的标准化测试和响应过程。{ngx_int_tn;ngx_str_t*expect;局部变量声明1 检查if(r-expect_tested||r-headers_in.expectNULL||r-http_versionNGX_HTTP_VERSION_11#if(NGX_HTTP_V2)||r-stream!NULL#endif){returnNGX_OK;}r-expect_tested一个标志flag。如果它已经是非零值通常是 1表示该请求的 Expect 头部已经被测试过了无需再测试。目的防止重复处理同一个请求的 Expect 头部。r-headers_in.expect NULLr-headers_in是存储解析后请求头部的结构体。expect是其中一个指针成员指向解析出的 Expect 头部的信息。如果它为 NULL表示请求头部中根本没有 Expect 字段。目的如果不存在 Expect 头部就不需要做任何事。r-http_version NGX_HTTP_VERSION_11r-http_version是一个整数表示请求的 HTTP 版本。NGX_HTTP_VERSION_11是一个宏代表 HTTP/1.1 的版本号。如果请求版本低于 1.1比如 HTTP/1.0则不支持 Expect 机制直接跳过。目的遵循 HTTP 协议规范Expect 头部仅在 HTTP/1.1 或更高版本中有效。#if (NGX_HTTP_V2)这是一个预处理指令表示如果 Nginx 编译时包含了 HTTP/2 支持那么下面这一行才有效。#endif表示结束。|| r-stream ! NULL在 HTTP/2 下每个请求都对应一个流streamr-stream指向一个流结构体。如果非空说明这是一个 HTTP/2 请求。HTTP/2 不使用Expect: 100-continue机制它有自己的流量控制所以跳过。目的避免在 HTTP/2 请求中错误地应用 HTTP/1.1 的 Expect 处理逻辑快速返回NGX_OK如果上述任一条件为真函数直接返回NGX_OK表示“测试通过无需进一步动作”。调用者会认为一切正常继续后续流程。r-expect_tested1;标记已经测试过将r-expect_tested标志设置为 1。作用当这个函数被再次调用时比如不同的模块或不同的阶段第一个条件r-expect_tested就会为真从而直接返回NGX_OK避免重复执行后面的发送100 Continue的逻辑。这确保了100 Continue最多只发送一次。expectr-headers_in.expect-value;获取Expect头部的值r-headers_in.expect指向一个结构体表示Expect 头部。该结构体中的value成员是一个ngx_str_t类型的变量存储了Expect 头部的具体值例如 “100-continue”。是“取地址”操作符这里取得value这个结构体在内存中的地址然后赋值给指针变量expect作用现在我们可以通过expect指针方便地访问Expect值的长度expect-len和数据expect-data。if(expect-len!sizeof(100-continue)-1||ngx_strncasecmp(expect-data,(u_char*)100-continue,sizeof(100-continue)-1)!0){returnNGX_OK;}检查值是否为“100-continue”expect-lenExpect 值的长度字节数例如 100-continue 有 12 个字符长度为 12。sizeof(100-continue)在 C 语言中字符串字面量100-continue实际存储时会包含一个结尾的空字符\0所以sizeof(100-continue)返回的是 1312 个字符 1 个空字符。减 1 后得到 12即实际字符数。expect-len ! sizeof(100-continue) - 1首先比较长度。如果长度不是 12那么这个值肯定不是100-continue条件成立。如果长度相等再执行第二个条件ngx_strncasecmp(expect-data, (u_char *) 100-continue, sizeof(100-continue) - 1)ngx_strncasecmp是 Nginx 提供的字符串比较函数。它比较两个字符串的前 n 个字符不区分字母大小写。如果相等返回 0否则返回非 0 值表示第一个不同的字符的差值。第一个参数expect-dataExpect 值的字符串数据。第二个参数(u_char *) 100-continue将字符串字面量强制转换为u_char *类型以匹配函数参数类型。第三个参数sizeof(100-continue) - 1要比较的字节数这里就是 12。! 0如果比较结果不等于 0意味着字符串不匹配。综合起来如果长度不同或者字符串内容不同不区分大小写整个条件为真。此时 Expect 头部虽然存在但它的值不是100-continue不是“100-continue”则返回成功对于不支持的Expect 值Nginx 选择忽略该头部直接返回成功。根据 HTTP 规范服务器对无法识别或不满足的 Expect 期望应该返回 417 Expectation Failed但 Nginx 这里的实现方式是宽松的只处理100-continue对其他值当作没有 Expect 头部一样继续处理请求。ngx_log_debug0(NGX_LOG_DEBUG_HTTP,r-connection-log,0,send 100 Continue);调试日志2 发送响应nr-connection-send(r-connection,(u_char*)HTTP/1.1 100 ContinueCRLF CRLF,sizeof(HTTP/1.1 100 ContinueCRLF CRLF)-1);if(nsizeof(HTTP/1.1 100 ContinueCRLF CRLF)-1){returnNGX_OK;}发送“100 Continue”响应send函数执行后返回实际发送出去的字节数。这个返回值被赋给变量n检查发送是否完整如果实际发送的字节数n等于要发送的总字节数说明完整的响应已经被成功地送入发送缓冲区。此时函数执行成功。成功则返回返回NGX_OK表示“成功处理了 Expect 头部”客户端已经收到100 Continue可以继续发送请求体。/* we assume that such small packet should be send successfully */r-connection-error1;returnNGX_ERROR;}设置连接错误并返回

相关新闻

AI Newsletter深度拆解:开源策略、具身智能与评估革命

AI Newsletter深度拆解:开源策略、具身智能与评估革命

1. 这份AI Newsletter到底在讲什么?——一个从业十年的AI内容老手拆解“信息过载时代”的真实价值你点开这份标题叫《This AI newsletter is all you need #90》的邮件,第一反应可能是:又一份堆满术语的行业简报?别急着划走。我从…

2026/7/4 23:51:06阅读更多 →
AI智能体记忆系统架构设计:从理论到LangChain实践

AI智能体记忆系统架构设计:从理论到LangChain实践

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度 如果你正在开发一个AI智能体,并且发现它每次对话都像“金鱼”一样只有7秒记忆,那么这篇文章就是为你准备的。…

2026/7/4 23:51:06阅读更多 →
鲸鱼优化算法(WOA)与XGBoost参数调优实战

鲸鱼优化算法(WOA)与XGBoost参数调优实战

1. 鲸鱼WOA-XGBoost模型概述 在数据科学和机器学习领域,参数优化一直是个让人头疼的问题。传统网格搜索和随机搜索不仅耗时,还容易陷入局部最优。最近我在一个气象预测项目中尝试了鲸鱼优化算法(WOA)与XGBoost的结合,效果出奇地好。这个组合特…

2026/7/4 23:51:06阅读更多 →
FModel:Unreal Engine游戏档案浏览器完整指南

FModel:Unreal Engine游戏档案浏览器完整指南

FModel:Unreal Engine游戏档案浏览器完整指南 【免费下载链接】FModel Unreal Engine Archives Explorer 项目地址: https://gitcode.com/gh_mirrors/fm/FModel FModel是一款基于C#开发的Unreal Engine档案浏览器,专为游戏开发者和逆向工程师设计…

2026/7/5 0:56:26阅读更多 →
显卡驱动彻底清理指南:3分钟掌握DDU专业工具

显卡驱动彻底清理指南:3分钟掌握DDU专业工具

显卡驱动彻底清理指南:3分钟掌握DDU专业工具 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/display-drivers-uninstaller 当你…

2026/7/5 0:56:26阅读更多 →
SQL注入从原理到实战:手工注入、绕过技巧与安全防御详解

SQL注入从原理到实战:手工注入、绕过技巧与安全防御详解

1. 项目概述:为什么我们需要深入理解SQL注入?如果你是一名Web开发者、安全测试人员,或者只是对网站后台如何运作感到好奇,那么“SQL注入”这个词你一定不陌生。它就像网络安全世界里的“经典咏流传”,从上世纪90年代末…

2026/7/5 0:56:26阅读更多 →
GPT5.5 辅助论文写作实践:选题生成、文献整理与摘要润色流程

GPT5.5 辅助论文写作实践:选题生成、文献整理与摘要润色流程

概要2026年,AI辅助学术写作已进入"精细化适配"时代。不再是单一的内容生成,而是覆盖"选题构思→文献处理→初稿撰写→润色优化→格式规范→定稿校验"全流程。GPT-5.5作为OpenAI 2026年4月发布的旗舰模型,在论文写作场景中…

2026/7/5 0:56:26阅读更多 →
网络安全渗透测试入门:从DVWA到在线靶场的实战训练指南

网络安全渗透测试入门:从DVWA到在线靶场的实战训练指南

1. 靶场入门:为什么说它是渗透测试的“新手村”与“演武场”如果你刚接触网络安全,对“渗透测试”这个词既感到兴奋又有些迷茫,不知道从哪里开始动手,那么“靶场”就是你绕不开的第一个关键节点。你可以把它理解为一个完全合法、安…

2026/7/5 0:56:26阅读更多 →
5步轻松掌握Winhance:Windows系统优化终极指南

5步轻松掌握Winhance:Windows系统优化终极指南

5步轻松掌握Winhance:Windows系统优化终极指南 【免费下载链接】Winhance-zh_CN A Chinese version of Winhance. C# application designed to optimize and customize your Windows experience. 项目地址: https://gitcode.com/gh_mirrors/wi/Winhance-zh_CN …

2026/7/5 0:51:26阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/5 0:01:08阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/5 0:01:08阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/5 0:01:08阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/5 0:01:08阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/5 0:01:08阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/5 0:01:08阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/4 1:16:56阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/4 2:33:55阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/4 2:33:55阅读更多 →