
后端开发工具【免费下载链接】gotenbergA developer-friendly API for converting many document formats into PDF files, and more!项目地址https://gitcode.com/gh_mirrors/go/gotenberg点击查看免费下载Gotenberg 是一个基于 Docker 的文档转 PDF API 服务其仓库不仅是可运行的二进制更是一套以自注册模块为核心、强调向后兼容与防御式编程的 Go 工程。本文以仓库根目录的GEMINI.md即CONTRIBUTING.md贡献指南为主线结合源码与配置逐层讲解从项目布局、Makefile 构建验证工作流到模块系统、错误处理、日志遥测等代码规范再到单元测试与 Gherkin 集成测试体系以及 Conventional Commits 提交与 PR 清单。读完本文你将掌握为 Gotenberg 新增模块、路由或 PDF 引擎功能的完整开发流程与验收标准。从两条铁律开始向后兼容与防御式编程Gotenberg 的贡献指南开篇就立下两条高于一切的规则所有后续规范都是它们的展开向后兼容Backward compatibility。CLI 标志flags、环境变量、API 表单字段form fields与 HTTP 端点任何一项都不得在未经讨论的情况下被重命名或删除。防御式编程Defensive programming。假定输入是畸形malformed的显式处理每一个错误生产代码路径上永远不要 panic。这两条规则直接决定了仓库内部大量设计标志读取工具ParsedFlags专门提供MustDeprecated*系列方法以支持新旧参数并存见 flags.go错误处理规范要求errors.Is而非strings.Contains而模块框架在注册时会对空 ID、空构造器做防御性校验见 modules.go。开发工具链一览贡献指南列出了完整的工具链要求与当前仓库的实际配置完全一致组件要求仓库证据Go Modulegithub.com/gotenberg/gotenberg/v8go.modGo 版本以go.mod为准当前为 Go 1.27.1go.modDocker构建镜像与集成测试必需MakefileNode.js用于 Prettier 格式化非 Go 文件当前为 24.15.0.node-versiongolangci-lintv2零警告通过配置见 .golangci.yml其中 golangci-lint 的导入分组gci配置与贡献指南的导入顺序规范一一对应standard 标准库、default 第三方、prefix(github.com/gotenberg/gotenberg/v8)项目自身三组以空行分隔见 .golangci.yml 的gci.sections。动手之前先讨论再写代码贡献指南要求非平凡改动遵循先沟通、后编码的流程先开 issue 或 draft PR说明需要改什么、拟议方案要改哪些文件、接口如何变化、涉及哪些表单字段以及会影响哪些集成测试标签tags。一个 PR 只做一件事。功能、bug 修复、重构必须分开提交。新增功能或路由时先写 Gherkin 场景再写 Go 代码如果路由发生变化要同步更新.bruno/下的 Bruno API 集合。这条测试先行的约束在测试体系中还会再次出现集成测试以.feature文件为起点详见后文集成测试小节。项目布局一份源码地图贡献指南给出的目录职责划分如下括号内是当前仓库中的实际证据cmd/gotenberg/ - 入口点wiring/启动无业务逻辑 pkg/gotenberg/ - 核心模块系统、接口、工具、mock pkg/modules/ - 功能模块api、chromium、libreoffice、pdfengines 等 pkg/standard/ - 通过 import 把所有标准模块装配起来 test/integration/ - Gherkin feature 文件 Go 测试基础设施 build/ - Dockerfile、字体、Chromium 配置 .bruno/ - Bruno API 集合镜像每一个路由入口点确实极简cmd/gotenberg/main.go只有导入cmd包和空白导入pkg/standard然后调用gotenbergcmd.Run()没有任何业务逻辑main.go。装配发生在pkg/standard/imports.go通过 12 个空白导入一次性引入api、chromium、exiftool、libreoffice、libreoffice/api、libreoffice/pdfengine、pdfcpu、pdfengines、pdftk、prometheus、qpdf、webhook等模块imports.go。每个模块在各自的init()中自注册于是仅靠导入即完成装配。关键接口集中在pkg/gotenberg/Module、Provisioner、Validator、Debuggable。每个模块实现Descriptor()并通过init()自注册见 modules.go。以pdfcpu模块为例可以清楚看到自注册的完整形态init()中调用gotenberg.MustRegisterModule(new(PdfCpu))Descriptor()返回模块 ID 与构造函数Provision()从环境变量读取引擎二进制路径Validate()校验路径存在pdfcpu.go。chromium模块同样以gotenberg.MustRegisterModule(new(Chromium))开头并在文件头部集中声明ErrInvalidEmulatedMediaType、ErrScreenshotSelectorNotFound等包级错误chromium.go。构建与验证一切从 Makefile 出发贡献指南明确规定所有构建与验证任务都走 Makefile不要直接运行go命令除非要调试某个具体包。下表完整覆盖指南中的命令矩阵命令用途何时使用make build构建 Gotenberg Docker 镜像跑集成测试或手动测试之前make run通过docker compose运行 Gotenberg 容器手动测试标志由 Makefile 变量与 compose.yaml 配置make telemetry启动 OpenTelemetry collector 与 OpenObserve本地测试遥测时make down停止所有 compose 容器手动测试结束后make godoc在localhost:6060提供 GoDoc校验文档make fmt格式化 Go 代码提交之前make lint静态检查 Go 代码零错误提交之前make prettify格式化非 Go 文件Markdown、YAML、JSON提交之前make lint-prettier检查非 Go 文件格式提交之前make test-unit运行单元测试提交之前make test-integration运行全部集成测试40 分钟超时提交之前对照 Makefile可以进一步确认这些目标的实现细节make build基于TARGET、DOCKER_REGISTRY、DOCKER_REPOSITORY、GOTENBERG_VERSION、DOCKERFILE变量执行docker build --target。仓库默认值来自 .envGOTENBERG_VERSIONsnapshot、DOCKER_REGISTRYgotenberg、DOCKER_REPOSITORYgotenberg、DOCKERFILEbuild/Dockerfile、TARGETgotenberg。构建变体时用TARGETgotenberg-chromium或TARGETgotenberg-libreoffice。make test-unitgo test -race ./...即带竞态检测跑全量单元测试。make test-integrationgo test -timeout 40m -tagsintegration -v通过--tags参数传入目标标签并支持PLATFORM如linux/arm64与NO_CONCURRENCY变量见 Makefile。make fmt除格式化外还执行go mod tidy优化依赖make lint-todo使用 godox linter 扫描// TODO债务标记是提交前检查的有益补充。集成测试标签很多指南明确要求只跑与改动相关的标签而不是全量套件make test-integration TAGShealth make test-integration TAGSchromium-convert-html make test-integration TAGSmerge,splittest/integration/README.md中给出了完整的可用标签分组表Chromium 组chromium、chromium-convert-html、chromium-screenshot-url、chromium-ssrf等、LibreOffice 组、PDF Engines 组merge、split、flatten、optimize、rotate、encrypt、watermark、stamp、metadata、bookmarks等、基础设施组health、debug、root、version、output-filename、prometheus-metrics、webhook、download-from。代码规范模块系统受 CaddyServer 启发的自注册架构Gotenberg 的模块系统Significantly inspired by caddyserver/caddy见 doc.go。核心约束如下每个模块位于pkg/modules/name/至少实现gotenberg.Module即Descriptor()方法并通过init()自注册。装配wiring统一发生在pkg/standard/。先判断功能能否归入已有模块再决定是否新建模块只有真正独立的关注点才值得新开模块。cmd/gotenberg/严格只做装配与启动禁止业务逻辑。模块描述符的结构如下modules.gotype ModuleDescriptor struct { // ID is the unique name (snake case) of the module. ID string // FlagSet is the definition of the flags of the module. FlagSet *flag.FlagSet // New returns a new and empty instance of the modules type. New func() Module }围绕模块生命周期框架定义了多个可选的进阶接口modules.goProvisioner根据 flags、环境变量、Context 等初始化模块Provision(*Context) error。ValidatorProvision 之后做校验Validate() error。App可被应用启动/停止的模块Start、Stop、StartupMessage。SystemLogger在启动时输出自定义系统消息。Debuggable提供额外的调试数据Debug() map[string]any。模块之间的依赖通过Context解析模块在Provision阶段用ctx.Module(kind)或ctx.Modules(kind)获取实现特定接口的其他模块实例Context.loadModule会按需调用目标模块的Provision与Validatecontext.go。ModuleDescriptor中可选定义FlagSet即模块专属的 CLI 标志入口点会汇总所有模块的标志并按环境变量覆盖EnvVarName将-转成_并大写见 flags.go。向后兼容弃用而不是删除CLI 标志、环境变量、API 表单字段、HTTP 端点以及任何改变现有行为的默认值都必须经过讨论才能变动。正确姿势是用fs.MarkDeprecated()标记旧名新旧两个名字同时注册、并存。如果改动确实破坏兼容性在 PR 描述中明确标注为 breaking change。ParsedFlags为此提供了全套MustDeprecated*读取方法当旧标志被显式设置f.Changed(deprecated)时优先读旧值否则读新值。这覆盖了字符串、字符串切片、布尔、整数、时长、字节数、正则等所有类型flags.go。Makefile 顶部的大段环境变量默认值如CHROMIUM_DENY_LIST^file:(?!//\/tmp/).*、API_DOWNLOAD_FROM_DENY_PRIVATE_IPSfalse正是这套兼容性体系的运行配置Makefile。错误处理贡献指南对错误处理的要求可以概括为五条每个错误都要用fmt.Errorf(description: %w, err)包裹上下文。绝不静默吞掉错误。用errors.Is匹配错误禁止strings.Contains。生产代码路径禁止 panic。防御式校验输入。仓库对此有大量呼应pkg/gotenberg定义了ErrPdfEngineMethodNotSupported、ErrPdfFormatNotSupported、ErrPdfEncryptionNotSupported等一系列哨兵错误供errors.Is匹配pdfengine.gochromium模块的包级错误同样按此模式组织chromium.gosupervisor.go中ErrProcessAlreadyRestarting、ErrMaximumQueueSizeExceeded被Run()内层循环以errors.Is精确处理实现重启中则短暂退避重试supervisor.go。错误信息区分客户端与运维视角面向客户端与运维人员的错误信息必须说清楚三件事失败的是什么、不明显时为什么、存在修复方案时怎么修。而内部错误只进入日志的fmt.Errorf包裹链不受此约束保持精准与技术化即可。具体分级要求客户端HTTP 响应体指出违规的表单字段及其合法取值绝不返回裸的http.StatusText()。运维启动、Provision、Validate指出需要设置的环境变量或标志以及被检查的路径或值。安全与过滤类错误对客户端保持笼统不暴露 allow/deny 列表或私网 IP 策略具体原因只记入运维日志。不使用模糊措辞while others may have failed 这类话术也不在面向人的修复建议里贴原始os.Stat或 exec 输出。这一点在出站网络过滤上体现得尤为典型outbound.go中ErrFiltered被调用方统一映射为通用的 403具体原因留在运维日志里防止客户端探测过滤规则outbound.go。日志context-aware 的 slog模块在Provision()阶段通过gotenberg.Logger(mod)获取自己专属的 slog logger实现在 telemetry.go。所有日志调用必须携带 contextlogger.DebugContext(ctx, msg) logger.InfoContext(ctx, msg) logger.ErrorContext(ctx, msg)这样在启用 OpenTelemetry 时trace/span ID 会被注入结构化日志实现日志与链路关联。仓库中有大量配套基础设施pkg/gotenberg/internal/log/提供标准输出 handler 与颜色输出telemetry.go定义了TelemetryConfig并校验日志级别error/warn/info/debug、格式auto/json/text、级别大小写lower/upper等取值telemetry.go。对应环境变量见 MakefileLOG_LEVELinfo、LOG_STD_FORMATauto、LOG_STD_ENABLE_GCP_FIELDSfalse等Makefile。遥测外部工具调用必须打 span指南要求所有外部工具调用Chromium、LibreOffice、PDF 引擎、webhook、下载都必须创建 OTEL span使用trace.SpanKindClient与semconv.ServerAddress(toolname)指标与 trace 分别通过gotenberg.Tracer()与gotenberg.Meter()获取。源码中有两处典型的落地点短生命周期外部二进制soffice、pdftk、qpdf、exiftool、pdfcpu统一在Cmd.Exec()中创建process.exec客户端 span并记录退出码与error.typecmd.go。进程监督器为排队等待与进程启动分别创建engine.queue.wait与engine.process.startspan并用gotenberg.process.start.reason属性标注启动原因first_start/unhealthy/max_requestssupervisor.go、supervisor.go。导入顺序导入分组由 gci 强制标准库 → 第三方 →github.com/gotenberg/gotenberg/v8三组之间空行分隔。这在 .golangci.yml 的gci.sections中配置standard/default/prefix(github.com/gotenberg/gotenberg/v8)custom-order: true由make lint强制执行。文档规范语气短句、陈述句先说明它做什么然后停止。以动作开头Validates font embedding而不是 This function validates font embedding。主动语态Gotenberg checks the profile而不是 The profile is checked by Gotenberg。不用破折号em dash用句号、冒号或逗号。不用 we 式的模糊表达Dont...而不是 We do not recommend...。Godoc每个导出的类型和函数都要有以标识符名称开头的 Godoc 注释如// OutboundDecision is the result of...。每个包应有doc.go内含// Package foo ...注释。例如pkg/gotenberg/doc.go的 Package gotenberg implements the core module system以及各模块目录下的doc.go。用[Name]方括号引用标识符便于 pkg.go.dev 自动链接。例如outbound.go的注释中 Callers pass the Pinned slice from [OutboundDecision]...outbound.go。代码注释解释为什么why而不是是什么what。不用编号步骤注释// 1. Do X不用带编号的分隔线// --- 8. Foo ---普通分隔线允许。不写复述代码的噪音注释如// Check if err is nil。相关处引用规范条款如 Per ISO 32000-2, Table 116...。技术债务用// TODO: [context]标记make lint-todo会用 godox 扫描。测试体系单元测试单元测试采用表驱动table-driven写法文件为*_test.go。指南特别要求优先复用pkg/gotenberg/mocks.go中现成的 mock 实现而不是自造新的 mock。该文件集中提供了ModuleMock、ProvisionerMock、ValidatorMock、DebuggableMock以及覆盖合并、拆分、加密、水印等全部能力的方法级PdfEngineMockmocks.go大幅降低了为模块编写测试的样板代码。集成测试Gherkin Godog testcontainers集成测试的选型与编排方式详见 test/integration/README.mdBDD 语言使用 Godog 运行 Gherkin 场景feature 文件位于test/integration/features/每个端点或能力一个文件。容器编排testcontainers-go负责 Docker 编排。每个场景都会起一个全新的 Gotenberg 容器另有一个gotenberg/integration-tools容器提供 PDF 校验工具verapdf、pdfinfo、pdftotext。入口点test/integration/main_test.go构建标签integration。测试数据test/integration/testdata/存放各种 HTML、Markdown、DOCX、XLSX、PDF 与证书文件。前提运行集成测试前必须先make build构建镜像全套套件 40 分钟超时因此只跑与改动相关的标签。典型 feature 文件片段chromium_convert_html.featurechromium chromium-convert-html Feature: /forms/chromium/convert/html Scenario: POST /forms/chromium/convert/html (Default) Given I have a default Gotenberg container When I make a POST request to Gotenberg at the /forms/chromium/convert/html endpoint with the following form data and header(s): | files | testdata/page-1-html/index.html | file | | Gotenberg-Output-Filename | foo | header | Then the response status code should be 200 Then there should be 1 PDF(s) in the response Then the foo.pdf PDF should have 1 page(s)step 定义位于test/integration/scenario/新增测试前应先阅读scenario.go与containers.go。断言库覆盖面很广状态码、响应头、PDF 页数、页面内容、PDF/A 与 PDF/UA 合规性可容忍 N 条失败规则、flatten/加密状态、文件嵌入、并发响应一致性等。写新测试的步骤源自 test/integration/README.md先在test/integration/features/创建或更新.feature文件并打上合适的标签如chromium chromium-convert-html新增标签要同步加入 Makefile 的TAGS注释块与标签表新增 step 定义要写进scenario/scenario.go并在InitializeScenario注册测试数据放入test/integration/testdata/。提交与 Pull Request提交信息遵循 Conventional Commits 规范type(scope): description。常用类型feat、fix、refactor、test、docs、chore、ci、build。scope 对应改动的模块或领域例如chromium、pdfengines、api。提交时只暂存具体文件禁止git add -A或git add .这保证了一个 PR 只做一件事的可审查性。提交前清单开 PR 前需要逐项确认源自贡献指南原文无向后兼容性回归。参见向后兼容。代码规范达标错误包裹、日志、遥测、导入顺序、无 panic、cmd/中无业务逻辑。文档规范达标每个导出标识符都有 Godoc、新包有doc.go、语气符合要求。make fmt make lint make prettify make lint-prettier全部零警告通过。make test-unit通过。相关的make test-integration TAGS...通过。若新增或修改了路由同步更新 Bruno 集合。延伸阅读以下文档与本次指南配套可在仓库内继续深入test/integration/README.mdGherkin step 参考、可用标签、编写新测试的流程。.bruno/README.md.bru文件格式、集合约定、路由更新检查清单。pkg/modules/pdfengines/README.md如何为 PDF 引擎新增功能Makefile 变量与对应标志。整体来看这份贡献指南不是泛泛的社区模板而是与仓库代码深度耦合的工程手册模块自注册机制决定了新增功能的第一性约束实现Descriptor()并在init()注册向后兼容铁律催生了MustDeprecated*标志体系与 Bruno 集合同步机制测试优先文化落实为先 Gherkin 后 Go的开发顺序。对想要深入 Gotenberg 内部、或在其基础上扩展定制能力的开发者来说沿着本文的路径即可完成从读懂布局到通过全部检查的完整闭环。赞分享后端开发工具【免费下载链接】gotenbergA developer-friendly API for converting many document formats into PDF files, and more!项目地址https://gitcode.com/gh_mirrors/go/gotenberg点击查看免费下载相关推荐Mac Mouse Fix把普通滚轮映射成macOS触控板手势的方法Mac Mouse Fix把普通滚轮映射成macOS触控板手势的方法 上周给客户看一份长文档我转了三次滚轮页面直接跳了一整屏。刚才看的那行字找不到了。桌面应用系统编程Lean 4 贡献者开发工作流指南构建、测试与代码提交规范Lean 4 贡献者开发工作流指南构建、测试与代码提交规范 导读 本文是一份面向 Lean 4 仓库贡献者的完整开发工作流指南核心内容源自仓库根目录的 AG编程语言编译器形式化验证语言运行时标准库Lighthouse CI 贡献者指南Monorepo 架构、开发工作流与测试体系详解Lighthouse CI 贡献者指南Monorepo 架构、开发工作流与测试体系详解 本篇技术指南围绕 Lighthouse CILHCI仓库的贡献规范开发工具CI/CD质量保障创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考