ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

ShowDoc 中的 Guzzle Services 版本演进全解析:从服务描述到命令式 API 客户端

ShowDoc 中的 Guzzle Services 版本演进全解析:从服务描述到命令式 API 客户端 文档知识库后端前端【免费下载链接】showdocShowDoc is a tool greatly applicable for an IT team to share documents online一个非常适合IT团队的在线API文档、技术文档工具项目地址https://gitcode.com/gh_mirrors/sh/showdoc点击查看免费下载本篇技术指南以 server/vendor/guzzlehttp/guzzle-services/CHANGELOG.md 为骨架结合该库在 ShowDoc 项目中的实际落地位server/vendor/目录下的 vendored 源码系统梳理 Guzzle Services 从 0.1.0 到 1.1.3 的关键演进脉络。读完本文你将理解服务描述Service Description→ 命令Command→ HTTP 请求这条核心链路的工作原理掌握请求位置Request Location、响应模型Response Model、参数校验与过滤、query 序列化等关键机制的底层实现并能够读懂这份 changelog 背后每一项修复对应的源码依据。一、Guzzle Services 是什么为什么它出现在 ShowDoc 里Guzzle Services 是 Guzzle Command 库的一份参考实现它用Guzzle 服务描述Service Description来描述 Web 服务自动完成请求序列化并把 HTTP 响应解析成易于使用的模型结构。其核心概念只有两个Description服务描述用 PHP 数组声明baseUri、operations操作、models响应模型例如 README.md 中的最小示例GuzzleClient把描述与底层 Guzzle HTTP 客户端组合起来让开发者直接调用$client-testing([foo bar])这样的命令式方法而不是手写 URL 与参数拼接。在 ShowDoc 仓库中该库以 Composer 依赖的形式固定在 server/vendor/guzzlehttp/guzzle-servicescomposer.json声明guzzlehttp/guzzle: ^6.2、guzzlehttp/command: ~1.0、PHP5.5。它的实际使用者是腾讯云对象存储 SDKserver/vendor/qcloud/cos-sdk-v5/src/Qcloud/Cos/Client.php直接继承GuzzleHttp\Command\Guzzle\GuzzleClient并通过new Description($service)加载服务描述这正是 ShowDoc 文件上传等场景对接 COS 的底层 HTTP 层。理解这份 changelog等于理解了 ShowDoc 依赖树中一个关键传输组件的全部病历。二、服务描述的核心机制理解 changelog 的前提在展开版本史之前先看三块与 changelog 中绝大多数 issue 直接相关的源码。2.1 Description描述即配置src/Description.php 负责把数组配置转成对象模型兼容旧写法baseUrl会被自动归一化为baseUriDescription.php#L56-L60操作是惰性创建的getOperation()首次访问时才把原始数组包装成Operation对象Description.php#L143-L150模型同样惰性创建为Parameter对象Description.php#L166-L175描述中不属于规范保留键的字段会存入extraData通过getData()读取。2.2 Operation一个操作 一个 HTTP 动作src/Operation.php 的构造函数文档完整定义了操作支持的配置键Operation.php#L26-L46配置键说明httpMethodHTTP 方法uriURI 模板支持{?foo}这种 RFC6570 变量展开parameters命令参数定义每个值是一个Parameter数组responseModel用于解析响应的模型名旧写法responseClass也被兼容见 Operation.php#L77-L80extends继承另一个操作见下文 2.3errorResponses错误响应声明code/phrase/classadditionalParameters未在 schema 中显式声明的额外参数所使用的模式deprecated/summary/notes/documentationUrl/data文档与元数据2.3 操作的 extends 继承Operation构造时若声明了extends会通过resolveExtends()从描述中取出被继承操作的配置做一层合并子配置优先parameters按参数名做一层合并Operation.php#L263-L278。这解释了 changelog 中 1.1.2 修复的Operations extends is broken in 1.1.1#145问题——继承机制是操作复用和减少重复声明的关键手段一旦回归所有依赖继承的 API 描述都会失效。2.4 Parameter参数的全部约束src/Parameter.php 的文档块是参数的权威规格Parameter.php#L88-L171包括typestring、number、integer、boolean、object、array、numeric、null、any也支持联合类型传数组required / default / static必填、默认值、是否禁止覆盖默认值getValue()中static或值为 null 且有默认值时返回默认值见 Parameter.php#L239-L246location请求位置默认为uri、query、header、body、json、xml、formParam、multipart1.x 起不再有postField/postFile见第五节sentAs线上传输名getWireName()返回sentAs ?: nameParameter.php#L325-L328这是 1.1.3 修复Use wire name when visiting array#152的核心机制filters值过滤器见 2.5format命名格式由SchemaFormatter处理见 2.6嵌套结构properties、additionalProperties、items、pattern、enum、minItems/maxItems、minLength/maxLength、minimum/maximum、$ref引用描述中的模型。2.5 filters参数值过滤链Parameter::filter()Parameter.php#L258-L297的执行顺序很有讲究format 与 filters 互斥声明了format就只走格式化且必须挂载在服务描述上否则抛RuntimeExceptiontype boolean且值非布尔时先用filter_var(..., FILTER_VALIDATE_BOOLEAN)转换依次执行每个 filter简单 filter 是Foo\Bar::baz这样的静态方法字符串复杂 filter 用[method ..., args [...]]数组其中value会被替换为当前值、api被替换为Parameter对象本身。Filters are applied twice#1341.1.1 修复正是这条过滤链被错误地执行了两遍Parameter type configuration causes issue when filters change input type#1471.1.3则是过滤器改变了输入类型后类型校验仍然按过滤前的类型判定导致的。2.6 SchemaFormatter命名格式src/SchemaFormatter.php 支持的格式包括format输出示例date-timeY-m-d\TH:i:s\ZISO 8601 UTCdate-time-httpRFC 1123 格式D, d M Y H:i:s \G\M\TdateY-m-dtime时间部分timestamp时间戳boolean-string布尔值转字符串输入既可以是数字时间戳、可解析的字符串也可以是\DateTime对象统一转为 UTC。boolean-string 作为受支持的 format 值正是 0.5.0 合并的 PR #63 加入的。三、1.x 时代2016-11 ~ 2017-10Guzzle 6 兼容与稳定性收尾1.0.0 是分水岭PR #109 使 Guzzle Services兼容 Guzzle 6guzzlehttp/guzzle: ^6.2同时修复了AbstractClient not found#117。此后的 1.0.1 ~ 1.1.3 基本围绕回归问题做密集修补。3.1 1.0.1回归修复批次Regression in array parameter serialization#128数组参数序列化回归由 PR #129 Fix serialization of query params 修复Unable to POST multiple multipart parameters#123多个 multipart 参数无法同时 POST与MultiPartLocation相关postField location not recognized after upgrading to 1.0#119升级后旧postField位置失效——这是第五节迁移指南的直接诱因combine method in Uri#101/ Undefined Variable#88URI 组合与未定义变量的健壮性修复PR #108 修复 baseUrl 与命令 URI 的组合PR #105 修复对不存在的GuzzleHttp\Psr7\Uri::combine的调用PR #127为压入 handler 栈的ValidatedDescriptionHandler命名validate_description见 GuzzleClient.php#L159-L161。3.2 1.1.x默认值、继承与序列化细节1.1.02017-01-31Serializer开始支持自定义查询参数序列化器PR #132 与 PR #130详见第六节同时修复 PUT 请求中postField参数抛异常#78、XmlLocation同名标签回归#82、HATEOAS 式非顶层对象列表#90等。1.1.12017-05-15修复filters 被应用两次#134、特定 URI 参数值不应被 urlencode#97PR #135 修复校验时不应当修改命令对象Do not mutate command at validationPR #138 支持在响应模型上使用 filtersPR #136 将属性暴露给父类。1.1.22017-05-19修复默认值在 1.1 中被忽略#146与extends 继承损坏#145。默认值机制见 Parameter.php#L239-L246只有静态值或值为 null 且有默认值时才会回落到默认值回归常常出现在校验器提前改写值之后。1.1.32017-10-06本仓库锁定的最新版Parameter type configuration causes issue when filters change input type#147过滤器改变输入类型后校验失效PR #152 Use wire name when visiting array遍历数组时应使用getWireName()即优先sentAs而非参数名保证sentAs重命名后数组场景下线上字段仍正确PR #144 Adding descriptive error message on parameter failure参数校验失败时给出更可读的错误信息对应 SchemaValidator 的getErrors()错误收集机制。四、0.x 时代2014-03 ~ 2016-10从雏形到 Guzzle 64.1 0.1.0 ~ 0.2.0起步阶段0.1.02014-03-15为初始版本。0.2.02014-03-30修复了联合类型参数校验失败#12——这正是 SchemaValidator::determineType() 中逐个尝试 type 数组中每个类型、命中即返回这一设计要解决的问题同时修复CommandException路径PR #2、更新composer.json依赖约束PR #14。4.2 0.3.0描述加载与 baseUri 模板化baseUrl 可以是字符串或 URI 模板PR #16Description构造时new Uri($config[baseUri])URI 模板能力由Serializer::createCommandWithUri()中的\GuzzleHttp\uri_template()展开Serializer.php#L138-L163从文件加载服务描述#15社区通过gimler/guzzle-description-loader插件实现composer.json的suggest字段明确建议了该包修复 XML 中字符串 0 被误过滤#20XmlLocation对零值字符串的处理回归。4.3 0.4.0Guzzle 5 适配与异常传播全面适配 Guzzle 5#57、PR #54自定义命令类PR #29可以为命令实例配置自定义类模型递归扩展PR #34模型支持递归的 extends 继承订阅者抛出的异常被吞掉#58由 PR #59 修复要求异常必须为GuzzleHttp\Command\Exception\CommandException实例否则会被包装这条规则后来沉淀进Deserializer::handleErrorResponses()的注释中见 Deserializer.php#L243-L249。4.4 0.5.0XML 属性与 format 补充XmlLocation 同名标签处理回归#51与非叶子子节点属性缺失#52修复PR #53文档补充 boolean-string formatPR #63即 SchemaFormatter 中的formatBooleanAsString。4.5 0.6.0Guzzle 6 兼容的前夜PR #109 让库兼容 Guzzle 6为 1.0.0 铺路baseUrl 中允许参数#102继续强化 URI 模板能力Runtime Exception Error is always empty#99异常消息为空的问题由 PR #85 改进调试信息JSON 响应模型映射增强#91null 值映射到模型属性PR #92、#80JSON 数组映射为 Model、#75模型属性为空时产生 noticePR #76、#73允许原始类型响应PR #74、#71/#72属性简写定义、#66errorResponses 从未被使用——由 PR #67 引入 ErrorHandler subscriber最终演化为Deserializer::handleErrorResponses()。4.6 errorResponses 的匹配逻辑Deserializer::handleErrorResponses()Deserializer.php#L255-L293是 changelog 中 #66/#67 的直接产物匹配规则值得单独说明遍历操作声明的errorResponses先按codeHTTP 状态码匹配若声明了phrase则要求状态码与reason phrase同时精确匹配同时声明了 codephrase 时命中即中断不可能有更精确的匹配只匹配到 code 则继续遍历找更精确的命中后抛出对应class异常完全未命中则交由 Guzzle 的http_errors选项处理。五、从 changelog 看 API 破坏性变更postField / postFile 的退役README 的 Transition guide from Guzzle 5.0 to 6.0 一节README.md与 changelog 中 #98、#119、#123 等 issue 互为印证postField和postFile两个请求位置在 Guzzle 6 时代被移除取而代之的是postField→formParam对应 FormParamLocationpostFile→multipart对应 MultiPartLocation。// 旧写法Guzzle 5——升到 1.x 后必须迁移 [ parameters [ foo [type string, location postField], bar [type string, location postFile], ], ] // 新写法Guzzle 6 / 本仓库 1.1.3 [ parameters [ foo [type string, location formParam], bar [type string, location multipart], ], ]Serializer构造时内置的默认位置注册表印证了 1.x 的最终形态Serializer.php#L36-L47body、query、header、json、xml、formParam、multipart七个位置配合uriURI 模板内联处理共八个参数落点。值得注意的是uri位置在prepareRequest()中被显式跳过Serializer.php#L82-L85因为它在createCommandWithUri()阶段已经通过 URI 模板展开了。六、Query 序列化1.1.0 引入的扩展点含完整代码changelog 1.1.0 的 PR #132 Bring more flexibility to query params serialization 是查询参数序列化的转折点。默认行为使用严格 RFC3986 规则http_build_query数组参数会序列化为$client-myMethod([foo [bar, baz]]); // 默认foo[0]barfoo[1]baz但很多真实 API 要求去掉数字下标输出foo[]barfoo[]baz。README 的 Cookbook 给出了完整的替换方案README.mduse GuzzleHttp\Command\Guzzle\GuzzleClient; use GuzzleHttp\Command\Guzzle\RequestLocation\QueryLocation; use GuzzleHttp\Command\Guzzle\QuerySerializer\Rfc3986Serializer; use GuzzleHttp\Command\Guzzle\Serializer; $queryLocation new QueryLocation(query, new Rfc3986Serializer(true)); $serializer new Serializer($description, [query $queryLocation]); $guzzleClient new GuzzleClient($client, $description, $serializer);实现层面src/QuerySerializer/目录提供了 QuerySerializerInterface.php 与 Rfc3986Serializer.php其第二个构造参数即是否使用foo[]风格对应测试 Rfc3986SerializerTest.php。Serializer的构造函数接受自定义位置数组并与默认位置合并$requestLocations $defaultRequestLocationsSerializer.php#L49因此你完全可以根据业务需求编写自己的QuerySerializerInterface实现并注入。七、验证、处理与响应位置两个开关与完整的管道GuzzleClient构造函数接受一个$config数组GuzzleClient.php#L21-L42配置项默认值作用defaults[]每个命令创建时合并的默认参数getCommand()中$args $this-getConfig(defaults)GuzzleClient.php#L78-L80validatetrue是否启用命令输入校验关闭后不再压入ValidatedDescriptionHandlerprocesstrue是否解析 HTTP 响应为false时Deserializer直接返回原始响应Deserializer.php#L78-L81response_locations内置六种自定义响应位置访问器请求与响应的完整管道可以概括为命令调用 ($guzzleClient-testing([...])) └─ Serializer::__invoke() // 命令 → PSR-7 Request ├─ createCommandWithUri() // URI 模板展开 baseUri 解析 └─ prepareRequest() // 按 location 访问器逐个 visit after └─ ValidatedDescriptionHandler // 输入校验SchemaValidator └─ Guzzle HTTP 传输 └─ Deserializer::__invoke() // Response → Result 模型 ├─ handleErrorResponses() // errorResponses 匹配与异常抛出 └─ visit(model, response) // before → visit → after 三段式访问响应侧Deserializer内置六个位置Deserializer.php#L51-L61body、header、reasonPhrase、statusCode、xml、json。响应模型的访问采用before()→visit()→after()三段式生命周期Deserializer.php#L22-L29 的类注释对此有明确说明after()阶段正是 JSON 访问器处理additionalProperties的时机。changelog 中 0.5.0 的 #51/#52XML 同名标签与属性问题、1.1.0 的 #82XmlLocation 回归等都属于这套位置访问器体系的边界修复。八、结合 ShowDoc 的落地实践ShowDoc 对 Guzzle Services 的使用方式是间接依赖server/vendor/qcloud/cos-sdk-v5是直接消费者。关键证据server/vendor/qcloud/cos-sdk-v5/src/Qcloud/Cos/Client.php#L92 中class Client extends GuzzleClient并执行new Description($service)即把 COS 的 API 声明为服务描述后交给 GuzzleClient 驱动server/vendor/qcloud/cos-sdk-v5/composer.json声明了对guzzlehttp/guzzle-services的依赖。这意味着 ShowDoc 的 COS 文件上传链路直接受益于本 changelog 中的一系列修复1.0.1 的multipart 多参数修复#123关系到文件上传时多个表单字段的正确组装1.1.3 的sentAs/wire name 修复#152关系到传输字段名的正确性query 序列化扩展点PR #132则为对接风格各异的云厂商 API 提供了定制入口。如果你想深入验证这些机制仓库内还提供了完整的测试套件tests/ 目录覆盖SerializerTest、DeserializerTest、ParameterTest、SchemaValidatorTest以及八个请求位置与六个响应位置的独立测试可作为阅读源码和二次开发的配套参考。结语从 2014 年 0.1.0 的雏形到 2017 年 1.1.3 的稳定收官这份 changelog 完整记录了一个描述驱动 HTTP 客户端库的成熟轨迹Guzzle 5→6 的兼容迁移、postField/postFile的退役、query 序列化的可插拔化、默认值与 extends 继承的回归修复、errorResponses 异常机制的沉淀。对本仓库ShowDoc而言它是支撑 COS 集成稳定性的底层依赖对读者而言理解这条演进线也就掌握了 Guzzle Services 服务描述、参数位置、过滤与格式化、响应模型解析这整套命令式 API 客户端的核心原理。赞分享文档知识库后端前端【免费下载链接】showdocShowDoc is a tool greatly applicable for an IT team to share documents online一个非常适合IT团队的在线API文档、技术文档工具项目地址https://gitcode.com/gh_mirrors/sh/showdoc点击查看免费下载相关推荐ShowDoc 中的 Guzzle PHP HTTP 客户端从 Composer 安装到 OAuth2 集成实战ShowDoc 中的 Guzzle PHP HTTP 客户端从 Composer 安装到 OAuth2 集成实战 本篇技术指南以仓库内 server/vend文档知识库后端前端Gradio Python 客户端 gradio_client 演进全解从 0.1.2 到 2.6.1 的 API 客户端设计与版本变迁Gradio Python 客户端 gradio_client 演进全解从 0.1.2 到 2.6.1 的 API 客户端设计与版本变迁 本文以 Gradio前端后端AI 应用Huly 服务端客户端库 hcengineering/server-client 深入解析从版本演进到源码实现Huly 服务端客户端库 hcengineering/server client 深入解析从版本演进到源码实现 hcengineering/server后端前端企业应用项目管理即时通讯CRM创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表