命名持久服务接口规范 0.3.0
请求命名持久服务文字 接受授权绑定名、对象名称、内部绝对网址、方法、查询键值列表、请求标头键值列表和文字正文。宿主先按当前程序的 DO 许可核对绑定名,再以 getByName 定位该绑定内的对象;不得以对象名选择其他绑定或外部网络。对象名称为非空且不超过 128 字符的 ASCII 字母、数字、下划线、连字符或斜线(斜线自 0.3.0 起允许,见文末“0.3.0 变更”)。内部网址只能位于 https://asset/ 或 https://internal/,其路径拒绝反斜线、控制字符、? 和 #;不得携带自带查询或片段。方法限 GET、HEAD、POST。查询参数最多 16 项,由宿主编码;请求标头仅允许精确名称 Origin、Content-Type、Cookie,最多 8 项且不得重名,值只含可见 ASCII 字符(0x20 至 0x7E)、首尾不得为空格且至多 8192 字节;GET/HEAD 正文必须为空,POST 正文最多 8 MiB(0.1.0 为 2 MiB)。正文按字节发送,不经 JSON 转义,任意字符原样送达。
宿主返回有效 JSON 对象文字:status 为上游整数状态,body 为完整 UTF-8 文字正文(宽松解码,非法序列成 U+FFFD,字节序标记去掉,同 Response.text()),headers 只包含上游存在的 content-type、location、set-cookie、x-yuyan-revision 四个小写名称和值。正文最多 8 MiB(0.1.0 为 2 MiB),超出则抛豫言异常;先看 Content-Length,无声明时流式累计。HTTP 4xx/5xx 仍是成功取得的响应。对象抛错或请求失败抛豫言异常(0.1.0 中此情形会使宿主崩溃,不可捕获)。宿主不得泄露其他响应头、句柄或当前程序之外的对象。当前 _start 边界以 JSON 文字传递结果;长期类型化入口可将其改成豫言记录与字节流。
0.2.0 新增:流式响应、增量读取与转发入站请求
0.2.0 只新增八个函数,请求命名持久服务文字 的签名与语义不变(限额提高与失败可捕获见上)。新增部分服务于“读云端项目对象的 SSE、NDJSON 长响应”与“把入站请求原样转给对象并回传其事件流”。
流式请求
请求命名持久服务流(绑定名, 对象名, 网址, 方法, 查询, 标头, 正文, 超时毫秒) 返回“(成功,响应柄或错误文)”。绑定名、对象名、网址、方法、查询、标头、正文的校验与 请求命名持久服务文字 完全相同(违规抛豫言异常,不触及对象),另加超时毫秒 1 至 900000(越界抛豫言异常),期限用 AbortSignal.timeout 覆盖“发请求、等响应头、读响应正文”的整次交换。不跟随重定向。请求失败(对象抛错、传输失败)或响应头到达前期满,返回“阴”和以 持久服务请求失败或超时: 或 持久服务请求超时 开头的错误文;成功返回“阳”和响应柄。正文按字节发送。
响应柄与增量读取
响应柄是不透明字符串,仅在创建它的事件内有效,不可保存、序列化或伪造;请求命名持久服务文字 内部也使用同一机制,不返回柄。不是本包签发的字符串一律抛豫言异常。同一柄的读取应当串行,不同柄可交错。
读取命名持久服务响应标头(柄, 名):返回响应标头值,名不区分大小写、须是 1 至 128 字节的合法标头令牌,缺失返回空字符串。此函数可读到x-yuyan-revision之外的任意响应标头,因为对象是应用自己的代码。读取命名持久服务响应状态(柄):返回 HTTP 状态码。读取命名持久服务响应文字块(柄, 最大字节):返回“(状态,文字)”,最大字节 1 至 65536。状态 0 数据块:宿主做流式 UTF-8 解码,跨块拆开的多字节字符正确拼接,非法序列成 U+FFFD,字节序标记去掉,文字绝不含半个字符,UTF-8 字节数不超过最大字节(小于 4 按 4 计),多出部分留待后续调用(上游连续送来 64 个以上空块的极端情形,可返回文字为空的状态 0,应用照常继续读取);状态 1 读尽(文字为空;无正文响应首读即得;流末残缺序列先以一个 U+FFFD 作状态 0 的块返回);状态 2 读取错误(文字为“名称: 消息”);状态 3 期满、已取消或有限读取超限已取消(文字为简短说明)。1、2、3 为终态,再调用返回同样结果。读取命名持久服务响应有限文字(柄, 字节上限):一次读完剩余正文,字节上限 1 至 8388608。状态 0 成功;状态 1 超过上限(先看Content-Length,声明超限则一字不读;无声明或不实则流式累计,超过即取消,恰等于上限不算超限);状态 2 错误;状态 3 期满或已取消。取消命名持久服务响应(柄):取消读取并对对象响应流执行 cancel,此后读取返回状态 3;幂等。对象能否即时回调其流的 cancel 取决于平台,不作保证。
以流式响应作最终响应
回应入站以命名持久服务原答(柄) 把 请求命名持久服务流 得到的响应(状态、标头、正文流,含 SSE)原样作为当前入站请求的最终响应。用于“先向对象发内部请求,检查状态并做其他处理,再把对象的事件流回传给客户端”。柄须由 请求命名持久服务流 签发;已开始增量读取(或已定局)的柄抛豫言异常;一次入站请求只能交付一个最终响应;交付后该柄不可再读,读取返回状态 3 与 已作终答。
转发入站请求
转发入站请求至命名持久服务(绑定名, 对象名, 网址, 查询, 保留标头名, 固定标头) 把当前入站请求转给对象,并以对象的响应作为当前入站请求的最终响应。它需要当前入站请求;无则宿主报错。
- 方法:取入站方法,限 GET、HEAD、POST,否则抛豫言异常。正文:POST 时把入站请求的正文流原样接给对象(不解析、不缓冲,对象可在请求尚未发完时开始读取),GET/HEAD 不带正文;入站正文若已被读取或已上锁,抛豫言异常。
- 网址与对象:对象名、内部网址(
https://asset/或https://internal/开头,路径规则同上)、查询(至多 16 项,由宿主编码)的规则同请求命名持久服务文字。 - 保留标头名:至多 16 项,逐名不区分大小写地只允许
Accept、Authorization、Content-Type、Cookie、CF-Connecting-IP、Idempotency-Key、If-None-Match、Last-Event-ID、Origin、Range与以X-Yuyan-开头者;不得重复;入站请求没有的略过。宿主只把这些标头的值原样交给对象,其余入站标头(如Host、Content-Length、Transfer-Encoding、X-Forwarded-*)一概不转发,且这些值不经过豫言程序的字符串。 - 固定标头:至多 8 项,名只允许
Accept、Content-Type、Origin与以X-Yuyan-开头者,值至多 8192 字节的可见 ASCII,不得与保留名或彼此重复,以固定值写入。 - 响应:对象的 Response(状态、标头、正文流,含 SSE)原样成为最终响应,宿主不缓冲、不改写;一次入站请求只能交付一个最终响应。不跟随重定向。对象抛错或请求失败抛豫言异常,不设响应。
失败分类
| 情形 | 类别 | | --- | --- | | 对象名、网址、方法、查询、标头、正文、超时、块上限、字节上限等参数违规;无效响应柄;转发时入站正文已被读取;已增量读取后作原答;对象抛错(文字版与转发) | 抛豫言异常,不发请求或不设响应 | | 绑定未授权或不存在 | 部署错误,宿主报错 | | 流式请求失败,或响应头到达前期满 | 返回“阴”和原因 | | 读取中对象出错、期满、取消、超限 | 读取函数的状态 2、3、1 | | HTTP 4xx、5xx | 成功响应,由应用按状态码处理 |
限额
对象名 128 字符;查询 16 项;请求标头 8 项、值 8192 字节;请求与响应正文 8 MiB;流式超时 900000 毫秒;块 65536 字节;有限整读 8 MiB;转发保留名 16 项、固定标头 8 项。
跨宿主一致性
不同宿主须满足:对象只经授权绑定内按名定位;先校验后发请求;流式 UTF-8 解码与拼接;期满后读取返回状态 3 并对对象响应流执行 cancel;取消对对象响应流执行 cancel;转发时不缓冲请求与响应正文,响应逐块随对象产生而到达;只转发白名单标头;不跟随重定向。
一致性样例
- 对象返回 3 个 SSE 事件,按 11 字节切块,增量读取得到的文字拼起来等于原文。
- 查询
a=1 2、b=中文&=:对象收到?a=1+2&b=%E4%B8%AD%E6%96%87%26%3D;Origin、Content-Type、Cookie原样到达;POST 正文(含引号、反斜线、换行、制表、表情)逐字节相同。 - 对象长久不出块,超时 300 毫秒:得已到的块,再得状态 3,宿主对对象响应流执行 cancel(原因
TimeoutError;能回调 cancel 的宿主可观察到);对象迟迟不回响应头:得“阴”和原因。 - 文字版:响应 8388608 字节成功,8388609 字节抛异常;请求正文 8388608 字节可发,多一字节抛异常;对象响应头
x-secret不出现在结果里。 - 先请求后作原答:向对象 GET
/events,读得状态 207 后回应入站以命名持久服务原答,客户端收到同样的状态、头与逐事件到达的正文;若先读过一块再作原答,抛异常。 - 转发:对象每 80 毫秒发一个事件,共 4 个,入站请求方逐个收到(首个与末个到达时刻相差不小于 150 毫秒);状态 207 与
x-yuyan-revision保留;入站 POST 请求体先发首块,对象读到首块后入站方才发第二块,仍能完成(缓冲整个请求体会死锁);只转发所列标头,Host、X-Cfg之类不转;保留名含Host抛异常。
0.3.0 变更:对象名称允许斜线
0.3.0 不新增函数、不改任何签名。对象名称的字符集由“ASCII 字母、数字、下划线、连字符”放宽为再加斜线 /,长度仍为 1 至 128 字符。原因:云工作台的项目对象自旧实现起就以 账户编号/项目编号 命名(Durable Object 的标识由名称派生,改名即丢失既有数据),接口必须能按原名定位它们。斜线可以出现在名称的任何位置,宿主只把名称交给 getByName,不把它当作路径、网址或文件名解释;其他字符(空格、点、冒号、反斜线、非 ASCII 等)仍一律拒绝,抛“持久服务对象名无效”。三个函数(文字版、流式版、转发)共用这一规则。
一致性样例(0.3.0 新增):对象名 7/3f2a9c1e-4b5d-4e6f-8a7b-9c0d1e2f3a4b(账户编号加斜线加项目编号)可用,宿主以该原名 getByName;a b、a.b、a\b、中文、空串、129 个字符的名称仍抛出可捕获的豫言异常。
边界
宿主不保证对象观察到取消,只保证读取一方立即得到状态 3、不再拉取对象。本包不提供:选择多个流中先到者的原语;对象之间的调用与广播;对象的创建与唯一标识(只按名定位);WebSocket;跨事件保存响应柄;自动重试。宿主执行事件的总时限由宿主配置,本包只保证按给定期限令读取失败。