首页 / 资讯中心 / 文章详情

MooTool next-compose DIFF-526 实战解析:HTTP 公网 smoke 白名单、PDF 合并表单保留与 P7 离线门禁

MooTool next-compose DIFF-526 实战解析:HTTP 公网 smoke 白名单、PDF 合并表单保留与 P7 离线门禁 ★ FEATURED ARTICLE
桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载本篇技术指南以 next-compose 开发切片文档 526-http-pdf-merge-smoke-p7-slice.md 为核心系统讲解 MooTool 下一代 Compose 桌面版next-compose在 F09 HTTP、F24 PDF、F17 二维码三个功能模块上的行为约定与验证方案并说明其与 P7 产品证据脚本、离线测试门禁的关系。读完本文你将掌握如何用环境变量开关跑通公网 smoke 测试、理解 PDF 合并/拆分后 AcroForm 表单与签名字段为何能保留而书签却不被复制、掌握二维码尺寸360.4 → 360归一化对齐的细节以及如何把“可选公网测试”与“离线必跑门禁”正确登记到验收文档中。一、切片背景DIFF-525 的收尾与定位本切片DIFF-526是开发切片序列中针对 DIFF-525「未做」事项的收敛切片集中补齐四类工作HTTP 公网走查F09 工具对httpbin.org与localhost/127.0.0.1的公开 smoke 测试PDF 合并表单保留F24 工具在合并/拆分后对页级表单与签名字段的保留行为产品证据脚本登记把可选 HTTP smoke 与 P7 离线门禁关系写进证据脚本P7 说明文档明确哪些事项仍属人工验收。切片明确声明不重复DIFF-525 中的非对称 Tab、本机 Cookie 单测聚焦在“公网走查 结构保留 脚本登记”这条独立主线上。相关切片均存放在 next-compose/docs/diff/ 目录与 DIFF-012PDFBox importPage 基础等历史切片共同构成 next-compose 的演进记录。二、F09 HTTP公网 smoke 的白名单机制与环境变量开关2.1 白名单实现仅放行 httpbin.org 与 localhost切片要求HttpEngine.isPublicSmokeUrlAllowed/resolvePublicSmokeUrl仅允许httpbin.org含子域与localhost/127.0.0.1。源码实现位于 HttpEngine.ktprivate val publicSmokeHosts setOf(httpbin.org, localhost, 127.0.0.1) /** Only httpbin.org and localhost are allowed for optional public HTTP smoke (see HttpEngineTest). */ fun isPublicSmokeUrlAllowed(url: String): Boolean { val uri runCatching { URI(url.trim()) }.getOrNull() ?: return false if (uri.scheme?.lowercase() !in setOf(http, https)) return false val host uri.host?.lowercase() ?: return false if (host in publicSmokeHosts) return true return host.endsWith(.httpbin.org) }该函数有三层校验URL 必须能被URI解析scheme 只能是http或httpsftp等一律拒绝host 必须命中httpbin.org、localhost、127.0.0.1三个精确值之一或以.httpbin.org结尾的子域。默认公网 smoke 地址定义在同文件顶部HttpEngine.ktconst val DEFAULT_PUBLIC_SMOKE_URL https://httpbin.org/get?sourcemootool-next-compose const val DEFAULT_PUBLIC_MULTIPART_SMOKE_URL https://httpbin.org/post?sourcemootool-next-composeresolvePublicSmokeUrl()读取环境变量MOOTOOL_HTTP_SMOKE_URL未设置时回落到默认地址无论走哪条路径最终都会再经过isPublicSmokeUrlAllowed强校验不通过直接check抛出异常从机制上杜绝 CI 或开发机误连第三方站点。2.2 测试双轨可选公网 smoke 与离线必跑 allowlist切片点名的两个测试全部位于 HttpEngineTest.ktpublicSmokeAllowlistPermitsHttpBinAndLocalhostOnly离线必跑L446-L454不依赖任何网络纯本地断言白名单行为assertTrue(HttpEngine.isPublicSmokeUrlAllowed(https://httpbin.org/get)) assertTrue(HttpEngine.isPublicSmokeUrlAllowed(http://127.0.0.1:8080/echo)) assertTrue(HttpEngine.isPublicSmokeUrlAllowed(http://localhost/health)) assertFalse(HttpEngine.isPublicSmokeUrlAllowed(https://example.com/)) assertFalse(HttpEngine.isPublicSmokeUrlAllowed(ftp://httpbin.org/get)) assertEquals(HttpEngine.DEFAULT_PUBLIC_SMOKE_URL, HttpEngine.resolvePublicSmokeUrl())optionalHttpBinPublicGetSmoke需开关、可跳过L456-L474通过 JUnitAssume.assumeTrue实现两级跳过Assume.assumeTrue( Set MOOTOOL_HTTP_PUBLIC_SMOKE1 to run httpbin/localhost smoke, System.getenv(MOOTOOL_HTTP_PUBLIC_SMOKE) 1, ) val url HttpEngine.resolvePublicSmokeUrl() val result HttpEngine.send( HttpEngine.emptyDraft().copy(url url, method HttpMethod.GET), requestId public-smoke, timeoutMs 15_000, ) Assume.assumeTrue( Network unavailable; record as 未测 in acceptance, result.ok || result.errorCode ! HttpErrorCode.NETWORK, ) assertTrue(result.ok, status${result.status} error${result.errorCode}) assertTrue(result.body.contains(httpbin.org) || result.body.contains(mootool-next-compose))这里体现了切片的完整语义默认 CI /desktopTest --offline跳过未设MOOTOOL_HTTP_PUBLIC_SMOKE1时第一个Assume直接跳过全程零网络无网时优雅降级即使开关打开但本机无网络第二个Assume会把结果标记为跳过并在验收文档中登记为未测而不是让测试失败污染门禁真正的断言请求成功且响应体包含httpbin.org或mootool-next-compose溯源参数。此外切片还覆盖了 multipart 公网走查变体optionalHttpBinMultipartPostSmokeL476-L507由MOOTOOL_HTTP_MULTIPART_SMOKE1独立开关控制POST 到DEFAULT_PUBLIC_MULTIPART_SMOKE_URL。2.3 与主请求引擎的关系公网 smoke 复用的是主引擎HttpEngine.send(...)HttpEngine.kt因此白名单治理的是“测试目标”而发送链路本身仍受既有约束保护10 MiB 响应上限MAX_RESPONSE_BYTES、clampTimeout1_000–120_000 ms超时钳制、cancel(requestId)取消能力以及HttpErrorCodeABORTED/TIMEOUT/NETWORK/INVALID_REQUEST/RESPONSE_TOO_LARGE错误分类。三、F24 PDF合并/拆分后的表单与签名字段保留3.1 技术路线importPage 子集 AcroForm 修复处理器切片对 F24 的行为描述是合并/拆分时importPage子集经PDFMergerUtility.appendDocumentAcroFormOrphanWidgetsProcessor/AcroFormDefaultFixup保留页级表单/签名字段 widget对齐 inspect 计数。对应实现见 PdfEngine.kt 的mergeopened.forEachIndexed { index, document - if (cancelled()) throw PdfException(cancelled, Cancelled) val pages parsePageSelection(sources[index].pages, document.numberOfPages) if (pages.isEmpty()) throw PdfException(empty-pages, No pages selected) PDDocument().use { subset - pages.forEach { subset.importPage(document.getPage(it - 1)) } repairImportedInteractiveForms(subset) merger.appendDocument(destination, subset) } pageCount pages.size }核心修复函数repairImportedInteractiveFormsPdfEngine.kt是关键所在/** Re-link widget annotations after importPage so inspect/merge retain AcroForm fields. */ private fun repairImportedInteractiveForms(document: PDDocument) { if (document.documentCatalog.acroForm null) { document.documentCatalog.acroForm PDAcroForm(document) } AcroFormOrphanWidgetsProcessor(document).process() AcroFormDefaultFixup(document).apply() }其原理可以这样理解PDDocument.importPage只搬运页面及页面级注解AcroForm 字段与 widget 注解之间的关联关系会丢失形成“孤儿 widget”AcroFormOrphanWidgetsProcessor负责把这些孤儿 widget 重新注册回 AcroFormAcroFormDefaultFixup做兜底修复确保合并产物中表单结构自洽合并前对每个子集先修复一次、合并完成后再对目标文档修复一次保证最终输出 inspect 计数与源文档对齐。拆分路径writePagesPdfEngine.kt采用完全相同的“子集 importPage → 修复 →appendDocument→ 再修复”流程因此拆分输出的表单/签名同样保留。3.2 书签不复制与 Electron pdf-lib 的对齐约定切片明确文档级书签仍不复制与 Electronpdf-libcopyPages一致。这一约定被固化为常量/** Document outlines/bookmarks are not copied on split/merge (same as Electron pdf-lib copyPages). */ const val ELECTRON_PARITY_OUTLINES_NOT_COPIED true也就是说表单、签名字段是“页级交互对象”随importPage携带并应保留而书签document outline是“文档级结构”在页级搬运语义下本就不复制。这是 next-compose 与 Electron 版本刻意对齐的跨技术栈行为契约。3.3 结构断言inspect 计数与单测验证切片点名的两个单测均在 PdfEngineTest.ktmergePreservesImportedPageFormAndSignatureWidgetsL111-L141构造一个含 1 个PDTextFieldname与 1 个PDSignatureFieldsig、并带 1 个书签的结构化 PDF与一个普通单页 PDF 合并后断言assertEquals(sourceInfo.formFieldCount, mergedInfo.formFieldCount, AcroFormDefaultFixup should register widgets copied with importPage) assertEquals(sourceInfo.signatureFieldCount, mergedInfo.signatureFieldCount) assertEquals(0, mergedInfo.bookmarkCount, Page-only merge does not copy document outlines (same as Electron pdf-lib copyPages))inspectCountsFormsBookmarksAndSignatureFieldsL143-L171强化拆分/合并的结构断言inspect对源文档计数表单 2、书签 1、签名 1拆分后表单/签名计数不变书签归零并断言ELECTRON_PARITY_OUTLINES_NOT_COPIED为真。两个测试覆盖了切片要求的两层目标对齐 inspect 计数合并后formFieldCount/signatureFieldCount与源一致与结构不膨胀书签明确不复制。PdfEngine.inspect/analyzeStructure的结构统计实现见 PdfEngine.kt。四、F17 二维码normalizeSize 与 Electron 对齐4.1 Double 重载与 roundToInt 语义切片要求QrEngine.normalizeSize(Double)对齐 ElectronqrTools.test.ts的360.4 → 360。实现见 QrEngine.ktfun normalizeSize(size: Int): Int size.coerceIn(MIN_SIZE, MAX_SIZE) fun normalizeSize(size: Double): Int { if (!size.isFinite()) return DEFAULT_SIZE return normalizeSize(size.roundToInt()) }细节要点Int重载直接coerceIn(120, 2000)其中MIN_SIZE 120、MAX_SIZE 2000、DEFAULT_SIZE 300Double重载先做有限性检查NaN/Infinity回落到默认 300再roundToInt()四舍五入后走 Int 钳制360.4.roundToInt()结果为360正是与 Electron 对齐的关键点生成时generatePng同样通过normalizeSize钳制尺寸QrEngine.kt。4.2 单测与跨版本 fixture单测normalizesSizeAndRejectsEmptyOrBrokenImagesQrEngineTest.kt同时覆盖边界钳制与异常路径assertEquals(120, QrEngine.normalizeSize(20)) // 下限钳制 assertEquals(360, QrEngine.normalizeSize(360)) assertEquals(360, QrEngine.normalizeSize(360.4)) // 对齐 Electron assertEquals(2000, QrEngine.normalizeSize(9999)) // 上限钳制 // empty / invalid-image / not-found 三个异常码切片提到的 fixture 位于 docs/fixtures/electron-next-qrTools-vitest.md其中将 ElectronqrTools.test.ts的normalizes QR sizes to the settings boundary20→120、360.4→360、9999→2000与QrEngineTest.normalizesSizeAndRejectsEmptyOrBrokenImages一一映射是 next-compose 与 Electron 行为对账的落点之一。五、产品证据脚本与 P7 离线门禁5.1 证据脚本登记切片要求三个证据脚本登记可选 HTTP smoke 与 P7 离线门禁关系product-evidence-common.sh 新增mootool_evidence_print_http_public_smoke_hint输出可直接复制的运行提示# Optional F09 httpbin/localhost only (default CI skips): # MOOTOOL_HTTP_PUBLIC_SMOKE1 MOOTOOL_HTTP_SMOKE_URLhttps://httpbin.org/get # cd compose_root ./gradlew :composeApp:desktopTest \ # --tests com.rememberber.mootool.next.compose.domain.HttpEngineTest.optionalHttpBinPublicGetSmoke --offline同文件还提供mootool_evidence_print_http_multipart_smoke_hintL35-L39与mootool_evidence_print_p7_smoke_hint等姊妹函数。verify-product-evidence-prep.sh 在非交互冒烟中先对prepare-p7-package-smoke.sh做bash -n语法检查随后 source 公共脚本并打印含mootool_evidence_print_p7_smoke_hint、mootool_evidence_print_http_public_smoke_hint在内的一批提示。该脚本同时验证各类证据预置脚本Vault 冲突、Git merge/rebase 冲突、IME 样本、托盘截图产出的真实文件例如data/vaults/json/sample.json与.git/MERGE_HEAD的存在性。prepare-p7-package-smoke.sh 把可选公网 HTTP smoke 明确标为不属于默认离线门禁echo ## Optional F09 public HTTP smoke (not part of default offline gate) echo # MOOTOOL_HTTP_PUBLIC_SMOKE1 runs HttpEngineTest.optionalHttpBinPublicGetSmoke (httpbin/localhost allowlist only). echo # Without network, mark 未测 in docs/acceptance.md — see docs/diff/526-http-pdf-merge-smoke-p7-slice.md.5.2 P7 离线门禁关系prepare-p7-package-smoke.sh定义的 P7 打包前本地检查序列为check-toolchain.shJDK 21 校验→:composeApp:printTooling --offline→:composeApp:verifyNativePackageMetadata --offline→:composeApp:desktopTest --offline→可选MOOTOOL_P7_BUILD_DIST1时packageDistributionForCurrentOS --offline。切片与脚本共同确立的门禁语义是离线必跑./gradlew :composeApp:desktopTest --offlineJDK 21是 P7 冒烟的事实门禁HTTP 公网 smoke 默认被Assume跳过可选增强有网且设MOOTOOL_HTTP_PUBLIC_SMOKE1时补跑 httpbin 走查验收边界无网时在 docs/acceptance.md 登记为未测P7 的三平台安装/公证/升级/卸载仍为人工验收脚本不代替。从 acceptance 现有记录看desktopTest门禁保持“--offline、--no-daemon公网 smoke 计 skipped”的运行口径例如 DIFF-667/668/669 批次均为 N/N2 通过、2 skipped与本文切片描述一致。六、验证命令汇总切片给出的完整验证清单按离线必跑与可选公网分组如下离线必跑JDK 21./gradlew :composeApp:desktopTest --offline或按类精确跑关键测试./gradlew :composeApp:desktopTest \ --tests com.rememberber.mootool.next.compose.domain.PdfEngineTest.mergePreservesImportedPageFormAndSignatureWidgets \ --tests com.rememberber.mootool.next.compose.domain.HttpEngineTest.publicSmokeAllowlistPermitsHttpBinAndLocalhostOnly \ --tests com.rememberber.mootool.next.compose.domain.QrEngineTest.normalizesSizeAndRejectsEmptyOrBrokenImages \ --offline可选公网有网时MOOTOOL_HTTP_PUBLIC_SMOKE1 ./gradlew :composeApp:desktopTest \ --tests com.rememberber.mootool.next.compose.domain.HttpEngineTest.optionalHttpBinPublicGetSmoke --offline MOOTOOL_HTTP_MULTIPART_SMOKE1 ./gradlew :composeApp:desktopTest \ --tests com.rememberber.mootool.next.compose.domain.HttpEngineTest.optionalHttpBinMultipartPostSmoke --offline无网时按切片约定在docs/acceptance.md登记未测而不是让 CI 变红。七、明确未做事项切片在“未做”节明确列出的后续事项写作本文时仍属人工/后续切片范畴不误标为已支持六套 CSS 皮肤、产品主窗全 Tab 走查multipart 文件上传公网走查PDF 书签/跨文档 AcroForm 完整策略安装镜像验收P7 三平台安装/公证/升级卸载托盘权限对话框与非对称 Tab 逐控件手工走查。这些边界在 prepare-p7-package-smoke.sh 中同样以“仍属 offline gate / 三平台安装·公证未验收”的注释形式反复声明阅读时应注意区分“代码已就绪”与“平台验收已通过”两类状态。赞分享桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载相关推荐MooTool Next Compose 视觉对齐 DIFF-082 实战紧凑搜索、HTTP 键值表与菜单密度全解析MooTool Next Compose 视觉对齐 DIFF 082 实战紧凑搜索、HTTP 键值表与菜单密度全解析 导读 本文以 MooTool 仓库中 n桌面应用开发工具MooTool Next Compose Vault Git 中止合并确认机制解析DIFF-108MooTool Next Compose Vault Git 中止合并确认机制解析DIFF 108 本文以 MooTool 仓库中 next compose桌面应用开发工具MooTool next-compose 开发实录JSON 更多菜单前置保存与随手记建夹路径解析DIFF-220MooTool next compose 开发实录JSON 更多菜单前置保存与随手记建夹路径解析DIFF 220 导读 本文面向 MooTool面向开发桌面应用开发工具上一篇终极指南如何使用 import_3dm 在 Blender 中完美导入 Rhino 3DM 文件下一篇VvvebJs 内置 Iconoir 图标库完整指南1000 SVG 图标的选择、引入与自定义创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站