Pingora 怎么使用 pingora-error 创建带上下文的错误并在过滤阶段映射为 HTTP 状态码
Pingora 怎么使用 pingora-error 创建带上下文的错误并在过滤阶段映射为 HTTP 状态码【免费下载链接】pingoraA library for building fast, reliable and evolvable network services.项目地址: https://gitcode.com/GitHub_Trending/pi/pingora在实现 pingora-proxy 的过滤阶段如request_filter时你经常需要在请求校验失败例如缺少必要的请求头时返回一个错误这个错误要携带自己的类型和一段可写进错误日志的上下文并且最终要决定向下游返回哪个 HTTP 状态码。pingora-errorcrate 提供了 Pingora 全家桶统一的Result类型与错误构建函数负责“创建和包装错误”而错误向 HTTP 状态码的映射则由 pingora-proxy 的fail_to_proxy()阶段完成。本文沿着官方错误处理指南、pingora-error 源码和 fail_to_proxy 默认实现走一遍这条完整路径。错误模型类型、来源、原因链和上下文一切以pingora-error中的Error结构体为中心。它由五个部分组成见 Error 定义字段说明etype: ErrorType错误类型如ConnectRefused、InvalidHTTPHeader、HTTPStatus(u16)esource: ErrorSource错误来源Upstream远端服务器、Downstream远端客户端、Internal内部逻辑或Unsetretry: RetryType该错误是否可重试Decided(bool)或ReusedOnlycause: OptionBoxdyn ErrorTrait Send Sync被包装的底层原因错误context: OptionImmutStr用户提供的任意字符串上下文crate 还导出了两个贯穿 Pingora 其他 crate 的类型别名/// The boxed [Error], the desired way to pass [Error] pub type BError BoxError; /// Syntax sugar for std::ResultT, BError pub type ResultT, E BError StdResultT, E;来源pingora-error/src/lib.rsErrorType是预定义的错误类型枚举涵盖连接、TLS、HTTP 协议、IO、文件等场景其中与本文最直接相关的是HTTPStatus(u16)源码注释写明它是“application error, will return HTTP status code”见 ErrorType 定义。如果预定义类型不够用可以用ErrorType::Custom(static str)或CustomCode(static str, u16)扩展自己的静态错误类型运行时动态生成的字符串更适合放在context里而不是类型里。创建带上下文的错误官方指南给出的选择原则见 errors.md Guidelines没有直接原因、但要附带上下文用Error::explain要包装一个已有的原因错误并补充上下文用Error::because指定错误来源的最小错误用new_in/new_up/new_down分别对应Internal/Upstream/Downstream来源。对应的签名见 Error 构建函数// 包装一个原因错误附加 context pub fn becauseS: IntoImmutStr, E: IntoBoxdyn ErrorTrait Send Sync( e: ErrorType, context: S, cause: E, ) - BError // 只有 context没有原因错误 pub fn explainS: IntoImmutStr(e: ErrorType, context: S) - BError官方示例场景是“预期请求头不存在时返回错误”见 errors.md Examplesfn validate_req_header(req: RequestHeader) - Result() { // validate that the host header exists req.headers() .get(http::header::HOST) .ok_or_else(|| Error::explain(InvalidHTTPHeader, No host header detected)) }这里validate_req_header在host头缺失时用Error::explain新建一个错误类型是InvalidHTTPHeader上下文是No host header detected这段上下文后续会出现在错误日志中。在过滤阶段把错误转换并传播校验函数返回的是普通错误而代理需要决定最终对下游返回什么状态码。pingora-error为此提供了一组作用在Result/Option上的 trait避免手写map_errtrait 方法等价操作行为Result::or_err(et, context)map_errError::because用新的ErrorType和上下文包装原错误原错误成为 causeResult::or_err_with(et, \|\| ...)同上context 由闭包构造适合运行时拼接字符串Result::explain_err(et, \|e\| ...)map_errError::explain用新错误替换原错误原错误不能移出作用域时Result::or_fail()map_errbecause(InternalError, , e)只是让非Error类型能通过?冒泡官方建议优先用or_errOption::or_err(et, context)ok_or(Error::explain(...))None时生成带上下文的错误Result::err_context(\|\| ...)map_errmore_context保留原错误类型和来源只追加一层上下文来源OrErr / OkOrErr / Context trait把这些串起来就是官方文档给出的请求过滤阶段完整写法见 errors.md其中request_filter是 ProxyHttp trait 的过滤阶段impl MyServer { pub async fn handle_request_filter( self, http_session: mut Session, ctx: mut CTX, ) - Resultbool { validate_req_header(session.req_header()?).or_err(HTTPStatus(400), Missing required headers)?; Ok(true) } }要点validate_req_header(...)产生的InvalidHTTPHeader错误在这里被or_err(HTTPStatus(400), Missing required headers)包装成新的HTTPStatus(400)错误原错误降为 cause?使过滤阶段直接以Err返回请求终止并进入错误处理流程官方文档同时说明Error的Display实现会打印整条 cause 链所以最初的InvalidHTTPHeader错误依然可见不会因为被包装而丢失见 errors.md。如果后续还想在传播链上加一层上下文而不改变错误类型和来源可以用more_context实现b().map_err(|e| e.more_context(b failed after a))more_context与Error::because的区别在于它保留原错误的类型和来源而because允许指定新的ErrorType且more_context只适用于Error类型because适用于所有实现std::error::Error的错误。fail_to_proxy() 如何把错误映射为 HTTP 状态码过滤阶段返回Err后请求会进入fail_to_proxy()阶段见 phase.md“This phase is called whenever an error is encounter during any of the phases above”。pingora-proxy 的默认实现按以下规则决定响应状态码见 ProxyHttp::fail_to_proxy条件映射结果etype是HTTPStatus(code)直接用该code来源为Upstream502来源为Downstream且类型为WriteError/ReadError/ConnectionClosed0连接已不可用不发送响应来源为Downstream的其他类型400来源为Internal或Unset500当 code 大于 0 时默认实现调用session.respond_error(code)把错误响应发往下游。所以上面or_err(HTTPStatus(400), ...)的错误经过这条默认路径下游收到的就是400 Bad Request——这正是 errors.md 对示例的结论“it will result in sending a400 Bad Requestresponse downstream”。同时phase.md 说明每个到达fail_to_proxy()的错误都会自动写入错误日志并调用request_summary()输出请求信息。也就是说你在过滤阶段附加的 context 字符串会随之出现在错误日志里这就是“带上下文的错误”在排障时的用途日志机制另见 error_log.md。如果默认映射不符合需要可以自己实现fail_to_proxy()重写响应逻辑——这是该钩子存在的目的“Users may write an error response to the downstream if the downstream is still writable”但本文的主路径使用默认实现。验证错误链的输出pingora-error的单元测试给出了Display输出和root_etype()的确定行为可作为核对错误链是否构造正确的参照以下为仓库单元测试中的断言属文档示例而非你程序的固定输出let e3 Error::new(ErrorType::InternalError); let e4 Error::because(ErrorType::HTTPStatus(400), test, e3); assert_eq!(format!({}, e4), HTTPStatus context: test cause: InternalError); assert_eq!(e4.root_etype().as_str(), InternalError); let e1: Result(), BError Err(Error::new(ErrorType::InternalError)); let e2 e1.or_err(ErrorType::HTTPStatus(400), another); assert_eq!(format!({}, e2.unwrap_err()), HTTPStatus context: another cause: InternalError);可以看出外层错误先打印自己的类型、context再以cause:递归打印内层错误链root_etype()可以取到最底层的错误类型。在自己的过滤器里判断“错误是否被正确包装”可以对照这种格式检查日志文本。端到端的验证方式则回到业务行为向服务发送一个缺少host头的请求例如按 examples 的main模式启动服务后用curl触发预期下游收到400 Bad Request响应且错误日志中出现HTTPStatus、context 以及被包装的InvalidHTTPHeadercause 链。限制可重试错误对代理行为的影响错误还有一个影响代理行为的维度——是否可重试。根据 errors.md如果错误被标记为可重试retry-ablepingora-proxy 会被允许对该上游请求进行重试部分错误仅在复用连接RetryType::ReusedOnly时才可重试用于处理“远端已丢弃了我们试图复用的连接”这类情况新创建的Error默认继承其直接原因错误的重试状态若未指定则视为不可重试。这意味着在过滤阶段用Error::explain创建的、不带原因的新错误默认是不可重试的——对“请求头缺失”这类客户端错误来说正是期望行为。如果你在because包装了一个可重试的上游错误新错误会继承该重试状态此时应确认代理重试符合你的预期。参考文件docs/user_guide/errors.md — 错误处理官方指南示例、Guidelines、Retry 说明pingora-error/src/lib.rs —Error/ErrorType/ErrorSource定义与or_err、explain、because等 APIpingora-proxy/src/proxy_trait.rs —fail_to_proxy()默认实现与状态码映射docs/user_guide/phase.md — 各过滤阶段与fail_to_proxy()的触发时机docs/user_guide/error_log.md — 错误日志级别约定【免费下载链接】pingoraA library for building fast, reliable and evolvable network services.项目地址: https://gitcode.com/GitHub_Trending/pi/pingora创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Hurl 命令行手册深度解读:用纯文本运行与测试 HTTP 请求的完整指南

Hurl 命令行手册深度解读:用纯文本运行与测试 HTTP 请求的完整指南

Hurl 命令行手册深度解读:用纯文本运行与测试 HTTP 请求的完整指南 【免费下载链接】hurl Hurl, run and test HTTP requests with plain text. 项目地址: https://gitcode.com/GitHub_Trending/hu/hurl 本文基于当前仓库中的 docs/manual.md 展开&#xff0c…

2026/9/13 19:05:53 阅读更多 →
共享充电桩小程序源码落地:从配置到上线避坑指南

共享充电桩小程序源码落地:从配置到上线避坑指南

简介:面向计算机专业毕业设计及课程设计场景,共享充电桩微信小程序项目是一套经过实际调试、可完整运行的毕业设计源码与配套文档,覆盖小程序前端、后端服务以及数据库设计,便于学生快速建立整体认识并直接用于答辩或课程作业。整…

2026/9/13 19:05:53 阅读更多 →
eino 中 reasoning_content 推理过程解析与实战指南

eino 中 reasoning_content 推理过程解析与实战指南

eino 中 reasoning_content 推理过程解析与实战指南 【免费下载链接】eino The ultimate LLM/AI application development framework in Go. 项目地址: https://gitcode.com/GitHub_Trending/ei/eino 用 eino 写 Agent,模型回传的消息里除了正文,…

2026/9/13 19:05:53 阅读更多 →

最新新闻

SpringBoot+Vue校园商铺管理系统开发实践

SpringBoot+Vue校园商铺管理系统开发实践

1. 项目概述太原学院商铺管理系统是一套基于SpringBootVueMySQL技术栈的校园商铺信息化解决方案。这个系统我花了三个月时间从零开发完成,目前已在太原学院实际运行半年多,稳定支撑着校内30多家商铺的日常运营管理。相比市面上通用的商业管理系统&#x…

2026/9/14 20:59:31 阅读更多 →
Solana 存储 Protobuf 定义与构建期代码生成机制解析(storage-proto 模块深度指南)

Solana 存储 Protobuf 定义与构建期代码生成机制解析(storage-proto 模块深度指南)

Solana 存储 Protobuf 定义与构建期代码生成机制解析(storage-proto 模块深度指南) 【免费下载链接】solana Web-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces. 项目地址: https://gitcode.com/GitHub_Trending…

2026/9/14 20:59:31 阅读更多 →
光热电站N-k安全约束建模与电力系统优化

光热电站N-k安全约束建模与电力系统优化

1. 项目背景与核心挑战在可再生能源占比不断提升的现代电力系统中,光热发电技术正展现出独特的优势。与传统光伏发电相比,光热电站(Concentrated Solar Power, CSP)通过熔盐储热系统实现了能量时移能力,其调节速率可达…

2026/9/14 20:59:31 阅读更多 →
typescript-eslint 的 eslint-scope 兼容测试套件:scope-manager 回归保障与源码剖析

typescript-eslint 的 eslint-scope 兼容测试套件:scope-manager 回归保障与源码剖析

typescript-eslint 的 eslint-scope 兼容测试套件:scope-manager 回归保障与源码剖析 【免费下载链接】typescript-eslint :sparkles: Monorepo for all the tooling which enables ESLint to support TypeScript 项目地址: https://gitcode.com/GitHub_Trending/…

2026/9/14 20:59:31 阅读更多 →
C++模板编程进阶:特化与缺省参数实战解析

C++模板编程进阶:特化与缺省参数实战解析

1. 项目概述:C模板编程的进阶探索在C编程语言的发展历程中,模板(Template)无疑是最强大且最具革命性的特性之一。它不仅是STL(标准模板库)的基石,更是现代C元编程的核心工具。本次我们将深入探讨…

2026/9/14 20:59:31 阅读更多 →
Python性能三重陷阱:内存、I/O与内核开销实战解析

Python性能三重陷阱:内存、I/O与内核开销实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 20:58:30 阅读更多 →

日新闻

AI音乐侵权案中的测试工程与版权保护技术

AI音乐侵权案中的测试工程与版权保护技术

1. 项目概述:当测试工程师遇上AI音乐侵权案去年夏天,我作为技术顾问参与了一起特殊的著作权纠纷案——某音乐平台AI作曲功能被指控批量侵权。这起案件的特殊性在于:原告方并非传统音乐人,而是一家拥有百万级曲库的数字音乐发行商&…

2026/9/14 0:00:26 阅读更多 →
嵌入式面试I2C与SPI深度解析:从协议到量产调试

嵌入式面试I2C与SPI深度解析:从协议到量产调试

1. 这份“高频知识点洞察”到底是什么,又为什么值得你花时间细读? 如果你最近在刷嵌入式开发岗位的招聘JD,或者正坐在工位上改第7版简历,又或者刚被面试官一句“讲讲I2C和SPI的区别”问得手心冒汗——那你不是一个人。过去两年我带…

2026/9/14 0:00:26 阅读更多 →
51单片机开环控制磁阻传感器的硬件匹配与代码实现

51单片机开环控制磁阻传感器的硬件匹配与代码实现

简介:本资源是一份面向嵌入式初学者与单片机课程实践者的51单片机开关磁阻电机(SRM)开环控制教学方案,聚焦磁阻位置检测、固定时序驱动与基础状态可视化。资源包含1个C语言主程序文件(zhuang600.c)实现电机…

2026/9/14 0:00:26 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/14 5:45:49 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/14 0:52:26 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/14 0:06:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/14 17:35:10 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/14 16:59:29 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/14 5:45:14 阅读更多 →