拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PSR-7 头部与查询串辅助方法全解析:Header、Query 与 ASCII 无区域大小写工具

PSR-7 头部与查询串辅助方法全解析:Header、Query 与 ASCII 无区域大小写工具 后端【免费下载链接】psr7PSR-7 HTTP message library项目地址https://gitcode.com/gh_mirrors/ps/psr7点击查看免费下载本篇技术指南聚焦 guzzlehttp/psr7 仓库中 docs/header-and-query-helpers.md 所讲解的辅助工具层如何解析结构化头部参数、按逗号拆分列表型头部、解析与构建查询字符串以及一批与区域设置无关的 ASCII 大小写转换与无大小写比较工具。读完本文你将掌握Header、Query与Utils三个静态工具类的核心 API 语义、底层实现细节与边界行为并能在自己的 HTTP 客户端、服务端中间件或协议解析代码中直接复用这些能力。辅助方法在 PSR-7 消息模型中的定位PSR-7 规范把 HTTP 消息抽象为MessageInterface请求与响应的公共部分提供getHeader()、getHeaderLine()、withHeader()等基本头部操作但规范刻意不规定“如何解析头部内部的结构”。guzzlehttp/psr7 通过独立的工具类补齐了这一层Header负责把头部值拆成可编程处理的结构化数据Query负责查询字符串的解析与构建Utils提供协议级字符串处理原语。关于消息层的基础行为可参考 PSR-7 Messages本页内容则是对它的补充。从源码结构看这三个类全部位于 src/Header.php、src/Query.php、src/Utils.php且都声明为final class并私有化构造函数——即只提供静态方法、不允许被实例化或继承属于典型的“工具类”设计。结构化头部参数解析Header::parse签名public static function parse(string|array $header): array作用把分号分隔的头部参数解析为关联数组每个逗号分隔的头部值对应一个数组没有值的参数按整数下标追加为值。parse()的内部流程见 src/Header.php分三步先把输入归一化为数组(array) $header逐值处理对每个值调用splitList()按逗号拆出独立的“条目”例如Link头中的每个uri; rel...对每个条目调用私有方法splitParameters()按分号切分参数再通过正则/[^]|[^]/将每个keyvalue拆成键值对——命中...形式如Link头中的角括号 URI或没有的参数时整体作为整数下标的值保存。splitParameters()src/Header.php实现了一个带引号感知的小型词法扫描器它会跟踪引号状态与\转义状态只在引号外遇到;才切分。因此fooa;b中的分号不会把值切断测试用例 tests/HeaderTest.php 中的fooa;b; barbaz、fooa;b\c; barbaz都验证了这一点。典型用例——解析Link响应头use GuzzleHttp\Psr7\Header; $link http:/.../front.jpeg; relfront; typeimage/jpeg, . http://.../back.jpeg; relback; typeimage/jpeg; $parsed Header::parse($link); // [ // [http:/.../front.jpeg, rel front, type image/jpeg], // [http://.../back.jpeg, rel back, type image/jpeg], // ]当 PCRE 内部出错例如测试中人为把pcre.backtrack_limit压到 1时parse()会抛出带preg_last_error_msg()说明的\RuntimeException见 tests/HeaderTest.php。列表型头部拆分Header::splitList签名public static function splitList(string|string[] $header): string[]作用把被定义为“逗号分隔列表”的 HTTP 头部拆成单个值并移除空值。典型用例$knownEtags Header::splitList($request-getHeader(if-none-match));getHeader()返回的可能是字符串数组PSR-7 允许多行同名单个头部值splitList()会先归一化数组再逐值扫描。扫描器同样是引号与转义感知的只有在引号外的逗号才作为分隔符从而正确处理foo,bar这类 ETag 内部含逗号的情况。normalizeProvider数据集中覆盖了 tests/HeaderTest.php 的foo, foo,bar, bar以及 tests/HeaderTest.php 中Cache-Control带引号逗号、转义空格、转义引号等场景。适用与禁用边界务必遵守适用accept、cache-control、if-none-match等按 RFC 定义为列表的头部禁用user-agent、set-cookie等不是列表语义的头部。它们的值本身可能含逗号拆分会破坏原始数据。另外传入非字符串值如整数、对象会抛出带说明文字的\TypeError见 src/Header.php 与测试 tests/HeaderTest.php。查询字符串解析Query::parse签名public static function parse(string $str, int|bool $urlEncoding true): array作用把查询字符串解析为关联数组。同一键出现多次时值自动合并为数组不会把 PHP 风格的嵌套数组foo[a]1foo[b]2解析成嵌套关联数组而是保留字面键名use GuzzleHttp\Psr7\Query; Query::parse(foo[a]1foo[b]2); // [foo[a] 1, foo[b] 2]urlEncoding参数决定解码策略src/Query.php取值解码行为true默认rawurldecode()并把替换为空格模拟parse_str()风格PHP_QUERY_RFC3986仅rawurldecode()保持字面加号PHP_QUERY_RFC1738urldecode()解码为空格false完全不解码键值按原始文本保留测试 tests/QueryTest.php 演示了varfoobar在 RFC3986 下得到foobar、在 RFC1738 下得到foo bar的差异。边界行为均可从 tests/QueryTest.php 的数据集验证空字符串返回[]没有的键值为null如foo null带的值为空字符串0 保留q.a这类点号键不像 PHPparse_str()会把.转成_不截断尾部等号dataabc得到abc重复键合并为数组且保留null与空串等特殊值qqqa得到[q [null, , a]]。查询字符串构建Query::build签名public static function build(array $params, int|false $encoding PHP_QUERY_RFC3986, bool $treatBoolsAsInts true): string作用把键值对数组构建成查询字符串。build()可以直接消费parse()的返回值完成“解析→重建”往返测试 tests/QueryTest.php 验证了parse($input, false)后再build(..., false)能还原原串。与http_build_query()的关键差异遇到值为数组的键时build()不会改写键名http_build_query()会为嵌套数组生成foo[0]之类的带下标键而是原样保留键并为数组中的每个元素生成一个keyvalue。例如[foo [a, b]]生成fooafoob。encoding参数src/Query.php控制编码器取值编码行为PHP_QUERY_RFC3986默认rawurlencode()空格 →%20PHP_QUERY_RFC1738urlencode()空格 →false不编码原样输出其他抛出\InvalidArgumentException(Invalid type)treatBoolsAsInts控制布尔值序列化为true时编码为0/1与http_build_query()默认一致为false时编码为false/true。测试见 tests/QueryTest.php。值类型与异常由私有方法normalizeValue()保证src/Query.phpnull只输出键不输出与值[foo null]→foo标量、实现__toString()的对象转字符串后编码嵌套数组、stdClass等不支持的类型抛出InvalidArgumentException(Query string values must be scalar, null, or stringable objects)非有限浮点数NAN、INF、-INF抛出InvalidArgumentException(Query string values must be finite; non-finite floats are not supported.)。相关测试见 tests/QueryTest.php。区域无关的 ASCII 大小写原语Utils::asciiToLower/asciiToUpper/asciiUcFirst签名public static function asciiToLower(string $string): string public static function asciiToUpper(string $string): string public static function asciiUcFirst(string $string): string作用与设计动机HTTP 协议元素头部字段名、方案名、主机名等按规范只对 ASCII 字母做大小写折叠。PHP 原生的strtolower()/strtoupper()/ucfirst()在 PHP 8.2 之前会遵循LC_CTYPE区域设置——这意味着在不同服务器区域下同一个字符串可能被转换成不同结果甚至影响非 ASCII 字节。这三个方法用strtr()做纯 ASCII 字母表映射src/Utils.php完全不受区域设置影响并且所有非 ASCII 字节原样保留。行为验证tests/UtilsTest.phpUtils::asciiToLower(X-Checksum); // x-checksum Utils::asciiToUpper(x-Checksum); // X-CHECKSUM Utils::asciiUcFirst(index); // Index Utils::asciiUcFirst(0abc); // 0abc首字符非字母原样返回 Utils::asciiUcFirst(); // 空串直接返回注意asciiUcFirst(x-a)返回X-a——它只作用于第一个字符不会像ucwords()那样把-之后的字母也大写。无大小写敏感比较Utils::caselessContains/caselessEquals/caselessRemove签名public static function caselessContains(string $haystack, string $needle): bool public static function caselessEquals(string $left, string $right): bool public static function caselessRemove(array $keys, array $data): array作用基于上述 ASCII 小写原语实现协议级的无大小写比较与过滤全部与区域设置无关。caselessContains先把haystack与needle转成 ASCII 小写再调用str_contains()src/Utils.php。测试覆盖Connection TIMEOUT after包含timeout为真、Connection reset不包含为假、空 needle 恒为真tests/UtilsTest.php。适合匹配错误信息中的关键词例如判断传输层错误文本里是否出现timeout。caselessEquals两边转小写后比较src/Utils.php。caselessEquals(HOST, host)为真非 ASCII 字符不会被“折叠”caselessEquals(\xC4\xB0, i)土耳其语点状大写 I为假tests/UtilsTest.php。caselessRemove把$keys与$data的键都转小写后剔除匹配项并保持原键名与顺序src/Utils.php。它被Utils::modifyRequest()内部用来按无大小写语义清理头部src/Utils.php例如remove_headers传[X-Checksum]也能删掉实际为x-checksum的头部。实战组合这几个方法配合使用即可实现“规范化头部是否存在/是否相等”的协议判断use GuzzleHttp\Psr7\Utils; $headers [Content-Type text/html, X-Checksum abc]; $remaining Utils::caselessRemove([x-checksum], $headers); // [Content-Type text/html] $isKeepAlive Utils::caselessEquals( $connectionHeader, keep-alive );相关阅读PSR-7 Messages —— 消息层基础头部行为Message Helpers —— 消息级辅助方法URI Helpers —— URI 解析、规范化与比较本页涉及工具的完整源码src/Header.php、src/Query.php、src/Utils.php行为佐证测试tests/HeaderTest.php、tests/QueryTest.php、tests/UtilsTest.php赞分享后端【免费下载链接】psr7PSR-7 HTTP message library项目地址https://gitcode.com/gh_mirrors/ps/psr7点击查看免费下载相关推荐实用工具集解析Guzzle PSR-7的辅助功能宝库实用工具集解析Guzzle PSR 7的辅助功能宝库 Guzzle PSR 7库提供了一系列强大的辅助工具类为HTTP消息处理提供了完整的解决方案。本文深入后端鸣潮自动化工具终极指南5个技巧解放你的游戏时间鸣潮自动化工具终极指南5个技巧解放你的游戏时间 你是否厌倦了在《鸣潮》中重复刷取声骸、完成日常任务的枯燥操作ok ww鸣潮自动化工具正是你需要的智能游戏助手GUI 自动化计算机视觉RPA人工智能react-native-reanimated v1 atan 节点详解反正切在声明式动画中的用法与原理react native reanimated v1 atan 节点详解反正切在声明式动画中的用法与原理 导读 atan 是 react native rea后端上一篇如何用Micro-World创建沉浸式3D场景从文本到交互式世界的完整教程下一篇VueDataV企业级数据可视化大屏的3个关键突破与实施策略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表