☰
仓颉中心仓通信规格详解:cjpm 制品包上传、下载与索引接口的完整设计
2026/10/14 16:55:45 网站建设 项目流程
  • 文档
  • 编程语言

【免费下载链接】cangjie_docs

仓颉编程语言开发者文档。

项目地址:https://gitcode.com/Cangjie/cangjie_docs
点击查看免费下载

仓颉中心仓(Cangjie Central Repository)是仓颉语言的三方库托管平台,而cjpm(仓颉项目管理工具)内置的中心仓客户端正是通过与中心仓仓库的一整套 HTTP 接口完成制品包的上传、下载与索引同步。本文基于文档仓库中的中心仓通信规格,逐接口拆解cjpm publish、依赖下载与cjpm update背后实际发起的请求格式(方法、URL、Header、Body 的二进制布局),并结合元数据规格、客户端配置与cjpm命令手册补充触发时机与排错方法,帮助你在发布制品失败或依赖解析异常时快速定位通信层问题。

通信基地址与鉴权来源

所有通信接口都以用户在cangjie-repo.toml中配置的repository.home.registry为基地址。根据中心仓客户端配置文档,该配置文件的典型格式为:

[repository.cache] path = "/path/to/repository/cache" # 本地存放路径 [repository.home] registry = "https://pkg.cangjie-lang.cn/registry" # 中心仓 url token = "user-token" # 用户个人 token

各字段与通信接口的关系如下:

  • repository.home.registry:中心仓仓库地址,上传/下载/索引三类请求的 URL 前缀。官方默认值为https://pkg.cangjie-lang.cn/registry;
  • repository.home.token:用户个人 token,仅在上传制品包时通过Authorization请求头携带,用于用户认证(token 可在中心仓官网个人中心创建、刷新和删除,参见中心仓官网章节);
  • repository.cache.path:本地缓存路径。若为相对路径则相对当前cangjie-repo.toml;留空时Linux/macOS下生效路径为$HOME/.cjpm,Windows下为%USERPROFILE%\.cjpm。假设最终生效路径为CACHE_PATH,则从中心仓下载的制品包源码会存放在${CACHE_PATH}/repository目录下。

cangjie-repo.toml有三个搜索位置,cjpm按以下顺序查找直到命中为止(与cjpm 使用手册中"项目管理配置文件说明"一节一致):

  1. 模块内与cjpm.toml同级目录的cangjie-repo.toml;
  2. 用户目录下.cjpm目录内的cangjie-repo.toml($HOME/.cjpm/cangjie-repo.toml或%USERPROFILE%\.cjpm\cangjie-repo.toml);
  3. 仓颉SDK中tools/config目录下的cangjie-repo.toml(SDK 默认自带该文件,全部为默认值)。

读取到第一个有效文件后即使用该文件,忽略更低优先级的配置。理解这一点很重要:如果你在SDK默认配置之外没有显式配置token,上传制品包时就会得到认证失败(401)。

制品包上传接口(对应cjpm publish)

cjpm publish会将bundle打包的cjpm模块对应的制品包和元数据发布到中心仓。根据制品包发布文档,bundle成功后会在编译产物目录(默认target)中生成模块名-版本号.cjp的制品源码包(tar.gz格式)和元数据文件meta-data.json;执行publish时,若任一文件缺失、或元数据中的制品包校验码与制品包不匹配,cjpm会先重新执行默认bundle流程再上传。

对应的API规格为:

项目规格
方法POST
URL(无组织模块)/pkg/${module-name}
URL(组织内模块)/pkg/${module-name}?organization=${org-name}
Header用户 token:Authorization=${token}
Body元数据 + 制品包两段二进制内容(见下)

请求体是"元数据段 + 制品包段"的自定义二进制布局,而不是简单的multipart表单。具体字节排布为:

┌────────────────────────────────────────────────────────────────┐ │ 元数据段 │ │ 元数据版本 (1 byte) 对应元数据内的 meta-version │ │ 元数据长度 (4 byte) 对应元数据的字节长度 m │ │ 元数据内容 (m byte) 对应整个元数据字节流 │ ├────────────────────────────────────────────────────────────────┤ │ 制品包段 │ │ 制品包版本 (1 byte) 对应索引内的 index-version │ │ 制品包长度 (4 byte) 对应制品包的字节长度 n │ │ 制品包内容 (n byte) 对应整个制品包字节流 │ └────────────────────────────────────────────────────────────────┘

几个关键点:

  • meta-version/index-version:分别对应元数据规格中meta-data.json顶层的meta-version字段(元数据规格版本号)和index索引内的index-version字段(索引规格版本号),当前文档示例中两者取值均为1。这种"1 字节版本 + 4 字节长度 + 内容"的自描述格式,使仓库端可以在不解析内容的情况下按规格版本做入库校验;
  • 版本号不体现在 URL 中:URL 只区分模块名(与所属组织),具体版本信息在元数据/索引内容中携带。例如上传无组织模块demo1的1.0.0版本时,url = /pkg/demo1;上传组织org的模块demo2的2.0.0版本时,url = /pkg/demo2?organization=org。这也意味着同一制品的不同版本走的是同一个 URL,冲突检测由仓库端基于"组织名 + 制品名 + 版本号"唯一性完成;
  • publish成功的隐含前提:cangjie-repo.toml中配置了有效 token;上传的制品包在仓库内唯一(不存在同组织名、制品名、版本号的已有制品);若制品属于某个组织,token 对应用户必须是该组织成员;制品包须通过中心仓安全扫描。

制品包下载接口(依赖解析 /install场景)

cjpm在成功进行依赖解析后,会基于最终确定的每个制品的版本,向中心仓发送下载对应制品包的请求。对应的API规格为:

项目规格
方法GET
URL(无组织制品)/pkg/${module-name}/version
URL(组织内制品)/pkg/${module-name}/version?organization=${org-name}
返回数据tar.gz格式的源码压缩包

与上传不同,下载 URL 中直接体现版本号,且不携带Authorization请求头(下载是公开读操作,不需要 token)。例如:

  • 下载无组织制品demo1的1.0.0版本制品包:url = /pkg/demo1/1.0.0;
  • 下载组织org的制品demo2的2.0.0版本制品包:url = /pkg/demo2/2.0.0?organization=org。

这个接口的触发场景包括:

  1. 在本地项目的cjpm.toml中以中心仓形式声明依赖(如dep1 = "1.0.0"、"org::dep4" = "4.0.0",格式详见制品包使用文档),执行cjpm build/run等命令时,依赖解析确定版本后按制品逐个下载,解压到CACHE_PATH下的本地缓存;
  2. 使用cjpm install [org::]name-version从中心仓安装可执行程序。根据 cjpm 手册install一节,例如cjpm install aoo-1.0.0会下载无组织制品aoo的1.0.0版本,cjpm install org::boo-2.0.0会下载组织org下制品boo的2.0.0版本,下载源码包后本地编译安装到${CACHE_PATH}/bin与${CACHE_PATH}/libs。

制品包本身与bundle产物结构一致(tar.gz源码包,文件名模块名-版本号.cjp),下载后可用tar直接解包。

索引下载接口(依赖解析 /cjpm update场景)

制品包下载之前,cjpm必须先知道某制品有哪些版本、每个版本的依赖约束与校验码——这些信息来自制品索引。cjpm在依赖解析过程中,或在执行cjpm update命令时,会向中心仓发送下载对应制品索引的请求。根据 cjpm 手册update一节:"update用于将cjpm.toml里的内容更新到cjpm.lock……如果配置了项目管理配置文件cangjie-repo.toml,cjpm update还将尝试更新本地的所有中心仓索引文件。"

对应的API规格为:

项目规格
方法GET
URL(无组织制品)/index/${mo}/${du}/${module-name}
URL(组织内制品)/index/${mo}/${du}/${module-name}?organization=${org-name}
返回数据制品索引文件,其中每行均为一个json索引条目

URL 中的${mo}/${du}是由模块名派生的两级目录前缀。从文档给出的示例可以看出其拆分规则:

  • 下载无组织制品aabbcc的索引时,url = /index/aa/bb/aabbcc:${mo}取模块名前 2 个字符(aa),${du}取接下来 2 个字符(bb);
  • 下载组织org的制品dep的索引时,url = /index/de/p/dep?organization=org:3 字符的模块名按"前 2 字符 + 其余"拆分,得到${mo}=de、${du}=p。

这种两级散列前缀(类似常见包仓库的 shard 设计)的目的是把索引文件打散到不同子路径下,避免单一目录下文件数爆炸。返回的索引文件是NDJSON(每行一个json索引条目)格式,每一行对应一个版本的索引条目。对照元数据规格,单条索引(index对象)的规格为:

{ "organization": "cangjie", // 组织名,为空则为无组织 "name": "demo", // 模块名 "version": "1.0.0", // 版本号 "cjc-version": "1.0.0", // 仓颉 SDK 版本号 "dependencies": [ { "name": "dep1", "require": "1.1.0", "target": null, // 平台隔离标识,null 表示不区分平台 "type": null, // 编译模式标识,null 表示不区分编译模式 "output-type": null // 编译产物类型标识,null 表示遵循对应源码模块的 package.output-type } ], "test-dependencies": [], // 测试依赖项,与源码依赖项格式一致 "script-dependencies": [], // 构建脚本依赖项,与源码依赖项格式一致 "sha256sum": "...", // 对应制品包的 SHA-256 校验码,用于验证制品包完整性 "yanked": false, // 制品包弃用标识,yanked == true 表示该制品包已被弃用 "index-version": 1 // 索引规格版本号 }

由此可见,索引下载与制品包下载在客户端协作的方式是:先GET /index/...拿到各版本的依赖需求、cjc-version与sha256sum,完成依赖解析选出目标版本,再GET /pkg/name/version下载制品包,并用sha256sum验证下载内容完整性。依赖冲突(如两个模块分别要求dep1的1.0.0和2.0.0)会直接导致解析失败,此时可用cjpm update刷新本地索引缓存获取最新制品信息,或按制品包使用文档中的方法(调整版本区间、replace强制指定等)解决。

返回码规格与故障定位

三类接口共用同一套返回码规格,完整列表如下:

返回码含义典型触发场景与排查方向
200成功—
400参数错误,可能是元数据或索引解析错误上传场景多为meta-data.json格式不符合元数据规格(如缺字段、meta-version不匹配);下载/索引场景多为 URL 中的模块名、组织名、版本号不符合制品规格(名称须为 3~64 位字母、数字、下划线,版本号须为Major.Minor.Patch格式)
401用户认证失败cangjie-repo.toml中repository.home.token未配置、已失效或填错;token 需在中心仓官网个人中心创建/刷新
403用户无权限或制品包名已被占用制品包名不区分大小写,大小写不同的名称视为同一制品包;组织制品需 token 对应用户为该组织成员
404文件不存在请求的制品名、组织名或版本号在中心仓中不存在(拼写错误或该版本从未发布)
409上传的制品包与仓库已有制品包冲突同组织名 + 制品名 + 版本号的制品已存在。制品包不可覆盖,应提升cjpm.toml中的version后重新bundle+publish
429请求频率超限请求过于频繁,稍后重试
>=500服务器故障中心仓服务端异常,稍后重试

几点实践提示:

  • 区分 401 与 403:401是"你是谁"没通过(token 无效/缺失),403是"你能不能做这件事"没通过(非组织成员,或名字撞车)。二者都出现在上传路径上,但排查动作完全不同;
  • 409不是版本升级通道:由于 URL 不携带版本号、且制品包以"组织名 + 制品名 + 版本号"保证唯一,重复发布同一版本必然得到409,正确的做法是修改版本后重新打包;
  • 名称大小写陷阱:制品包名在仓库端按不区分大小写处理,Demo与demo是同一个制品名,命名时容易因此误判"名字可用";
  • 429的规避:批量操作(如连续publish多个版本、大范围update)时注意控制请求节奏。

通信规格小结

从cjpm客户端视角,一次完整的中心仓交互链路可以归纳为:

依赖解析阶段 cjpm update / build / run ├─ GET /index/${mo}/${du}/${name}[?organization=org] 拉取 NDJSON 索引(含依赖约束、sha256sum、yanked) └─ GET /pkg/${name}/${version}[?organization=org] 下载 tar.gz 制品包并做 SHA-256 校验 发布阶段 cjpm bundle && cjpm publish └─ POST /pkg/${name}[?organization=org] Header: Authorization=${token} Body: [meta-version(1B) + len(4B) + meta-data.json(mB)] + [index-version(1B) + len(4B) + 制品包(nB)]

三组接口在 URL 命名上形成了清晰的对称关系:上传用/pkg/${name}(无版本,写入),下载用/pkg/${name}/${version}(带版本,读取),索引用/index/${mo}/${du}/${name}(两级散列前缀,读取);组织统一通过organization查询参数表达,无组织制品则省略该参数。掌握这套规格后,无论是调试publish的 401/403/409 错误、验证下载包完整性,还是理解cjpm update刷新索引缓存的机制,都有了可对照的协议层依据。

相关文档索引

  • 中心仓概述:中心仓三大组件(官网、客户端、仓库)划分;
  • 中心仓制品规格:制品包/制品/组织的定义与命名规则;
  • 中心仓客户端配置:cangjie-repo.toml字段与搜索顺序;
  • 制品包发布:bundle打包范围规则与publish流程;
  • 制品包使用:中心仓依赖声明格式、版本区间与冲突解决;
  • 中心仓元数据规格:meta-data.json与索引条目字段详解;
  • 中心仓通信规格(原文,中文) / 英文版本:本文所基于的通信规格定义;
  • cjpm 使用手册:update、bundle、publish、install命令的完整参数说明。
  • 文档
  • 编程语言

【免费下载链接】cangjie_docs

仓颉编程语言开发者文档。

项目地址:https://gitcode.com/Cangjie/cangjie_docs
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询