网页上游接口规范 0.2.0
本包用于同时持有当前入站请求与被授权出站 HTTPS 来源的宿主。请求授权网页上游 接受绝对 URL、方法、请求标头列表、正文文字和超时毫秒数。宿主须对每次请求核对当前程序许可的完整来源(方案、主机、端口),拒绝 URL 凭据、非 HTTPS、未授权来源与自动重定向;不能先发请求再核对。首版方法限 GET、HEAD、POST;请求头只允许 Authorization、Content-Type、Accept、X-Yuyan-Request-ID,不允许重复,最多 16 项;GET/HEAD 正文必须为空,其他正文至多 2 MiB;超时范围为 1 至 180000 毫秒,覆盖“发请求、等响应头、读响应正文”的整次交换。传输失败或超时返回阴和错误文字,成功返回阳和仅本次入站请求有效的响应柄。HTTP 错误状态仍属于成功取得的响应。响应柄不得在请求间保存或伪造;宿主逐次核对归属。
请求头的值须只含可见 ASCII 字符(0x20 至 0x7E)、首尾不得为空格:Authorization 至多 8192 字节,其余至多 512 字节;X-Yuyan-Request-ID 的值须恰为 36 个字符,只含小写十六进制数字与连字符。名与值不合规抛豫言异常,不发请求。
读取网页上游状态 返回原上游状态。读取网页上游癸象正文文 一次性读取有效 JSON 正文,规范化后最多 2 MiB;它消耗上游正文。回应入站以上游流 保持上游正文流,不缓冲或改写字节,并以状态 200 回应当前入站请求。它只接受 Content-Type、Cache-Control、X-Yuyan-Model、X-Content-Type-Options 四种响应头,至多 8 项,不允许重名;其他头和无效值失败。它占用当前入站请求唯一的最终响应,并消耗响应柄;此前若已读取正文或设置最终响应则失败。应用先检查上游状态再选择流式成功响应或错误答复。
当前 _start 装载边界用不透明文字标识响应柄。此标识是本次请求内的宿主资源,不是 URL、数据正文或可移植的序列化格式。长期类型化入口可用名义资源类型替换标识,不改变授权与流语义。
0.2.0 新增:增量读取与动态公网 HTTPS 上游
0.2.0 新增四个读取函数与 请求公网HTTPS上游,并给请求标头增加 X-Yuyan-Request-ID。请求授权网页上游 等 0.1.0 函数的签名与语义不变(仅上述标头值校验为新增的收紧)。新增部分服务于“向服务商上游发 POST,边读 SSE/NDJSON 边转发并计费”的应用。
响应柄与增量读取
请求授权网页上游 与 请求公网HTTPS上游 签发的响应柄,都可用于 读取网页上游状态 与下列读取函数;不是本包签发的字符串一律抛豫言异常。响应柄仅在创建它的事件内有效,同一柄的读取应当串行,不同柄可交错。增量读取会消耗并锁定响应正文:某柄一经开始增量读取(或已定局),读取网页上游癸象正文文 与 回应入站以上游流 对它抛豫言异常;要整体读取应改用 读取网页上游有限文字。
读取网页上游标头值(柄, 名) 返回响应标头值,名不区分大小写、须是 1 至 128 字节的合法标头令牌,缺失返回空字符串。
读取网页上游文字块(柄, 最大字节) 返回“(状态,文字)”,最大字节须在 1 至 65536 之间,否则抛豫言异常。
- 状态 0:数据块。宿主做流式 UTF-8 解码:跨上游块拆开的多字节字符正确拼接,非法序列各换成 U+FFFD,流首的字节序标记去掉,文字绝不含被截断的半个字符;不足一个完整字符的上游块不单独返回,宿主继续读取(上游连续送来 64 个以上空块的极端情形,可返回文字为空的状态 0,应用照常继续读取)。每次返回文字的 UTF-8 字节数不超过最大字节(小于 4 按 4 计);过大的上游块或因 U+FFFD 而超出的部分留在宿主,由后续调用依序返回。
- 状态 1:正文读尽,文字为空(无正文的响应首次读取即得)。流末尾残缺的字符序列先以一个 U+FFFD 作状态 0 的块返回,再返回状态 1。
- 状态 2:读取错误,文字为平台报告的原因,形如“名称: 消息”。
- 状态 3:期限已满,或应用已取消,或有限读取因超限已取消;文字是简短说明,仅供诊断。期满时宿主同时取消上游。
- 状态 1、2、3 是终态,此后再调用返回同样的终态与文字。
读取网页上游有限文字(柄, 字节上限) 一次读完剩余正文,字节上限须在 1 至 8388608 之间,否则抛豫言异常。状态 0:成功,文字为剩余正文(含尚未交付的部分);状态 1:超过上限,文字为空,宿主已取消上游——先看 Content-Length,声明超限则一字不读,无声明或不实则流式累计,累计原始字节超过上限即取消,超出部分不返回,恰等于上限不算超限;状态 2:错误;状态 3:期限已满或已取消。
取消网页上游(柄) 取消对响应正文的读取并对上游响应流执行 cancel(对外发连接即断开连接),此后读取返回状态 3;幂等,无效的柄抛豫言异常。上游能否即时观察到取决于平台,不作保证。
动态公网 HTTPS 上游
请求公网HTTPS上游(网址, 方法, 标头, 正文, 超时毫秒) 返回“(成功,响应柄或错误文)”,用于应用在运行时登记的、无法列入静态来源清单的上游(例如服务商自己填写的模型端点)。
- 许可:应用须声明“允许动态公网 HTTPS”。云工宿主现以程序许可
OUTBOUND_ORIGINS含通配来源https://*表示;此通配来源只用于本函数,不使请求授权网页上游放行任何真实来源。宿主可另设等价形式(如PUBLIC_HTTPS)。未声明则抛豫言异常,不发请求。 - 网址规则(适配在发请求前逐次严格校验,通过后以 URL 规范化的完整网址发出):原文 1 至 2048 字节,只含可见 ASCII,无空白、控制字符、反斜线、问号、井号;以
https://开头(小写);无用户信息(含@)、无查询、无片段,路径任意;主机名(规范化后)只含a-z、0-9、.、-,至少含一个点,不以点开头或结尾,无连续点,每段 1 至 63 字符且不以连字符开头或结尾,总长 3 至 253,末段不得全为数字——由此拒绝 IPv4 字面量及其十进制、十六进制、八进制写法,方括号形式的 IPv6 因含非法字符而拒;拒绝localhost、*.localhost、*.local、*.internal、*.localdomain、*.arpa(含*.home.arpa)、*.lan、*.home、*.corp、*.intranet、*.private;带点的非 ASCII 域名须已是xn--形式。 - 端口规则:省略(即 443)、443、2053、2083、2087、2096、8443、11434,以及 8000 至 9999;其余(含全部小于 1024 的端口、10000 及以上除 11434 者)拒绝。选取依据:443 与 Cloudflare 代理支持的 HTTPS 备用端口,8443 与 8000 至 9999 为常见应用高位端口,11434 为常见本地模型服务端口。
- 方法:精确的
GET或POST;GET的正文必须为空。 - 标头:至多 8 项;名只允许
Content-Type、Accept、X-Yuyan-Request-ID(不区分大小写,不得重复);值规则同上(除请求编号外至多 512 字节的可见 ASCII,请求编号须恰 36 个小写十六进制与连字符字符)。不允许Authorization、Cookie等。 - 正文:至多 2 MiB,按字节发送,不经 JSON 转义。
- 超时毫秒:1 至 900000,覆盖发请求至读完正文的整次交换。
- 不跟随重定向:3xx 作为成功响应返回,状态码与
Location可读,由应用当成“服务商请求失败”。 - 失败:许可未声明与参数违规(方法、标头、正文、超时)抛豫言异常;网址不合公网规则、传输失败、响应头前期满返回“阴”和原因(此为可恢复情形,应用按“服务商不可达”处理);成功返回“阳”和响应柄,读取与取消同上。
网址规则只约束网址的形式。名称解析后落到私有地址的情形(如公开域名解析为内网地址)由平台的出站网络策略约束,本接口不替代;应用仍应在登记端点时做同样的校验。
失败分类
| 情形 | 类别 | | --- | --- | | 请求头、方法、正文、超时、块上限、字节上限、标头名等参数违规;无效响应柄;已增量读取后再整读或转流答;公网函数无许可 | 抛豫言异常,不发请求 | | 未授权来源(静态函数)、发请求失败、响应头前期满;公网网址不合规则 | 返回“阴”和原因 | | 读取中上游出错、期满、取消、超限 | 读取函数的状态 2、3、1 | | HTTP 4xx、5xx、3xx | 成功响应,由应用按状态码处理 |
限额
请求头 16 项(公网 8 项);请求头值 512 字节(Authorization 8192);请求正文 2 MiB;静态超时 180000 毫秒,公网 900000 毫秒;块 65536 字节;有限整读 8 MiB;读取网页上游癸象正文文 沿用 2 MiB。
跨宿主一致性
不同宿主须满足:网址与来源核对先于发请求;流式 UTF-8 解码与拼接;期限覆盖全程且期满后读取返回状态 3 并对上游流执行 cancel;取消对上游流执行 cancel;先看声明长度再读;不跟随重定向;公网网址规则逐条一致。
一致性样例
- 5 帧 SSE 经静态来源或公网函数读取,文字与累计字节和整体一致(同授权服务样例)。
- 公网函数拒绝并返回“阴”(不发请求):
https://127.0.0.1/x、https://0x7f.0.0.1/x、https://2130706433/x、https://0177.0.0.1/x、https://127.1/x、https://[::1]/x、https://localhost/x、https://LOCALHOST./x、https://a.localhost/x、https://db.internal/x、https://router.home.arpa/x、https://user:pw@api.provider.com/x、https://api.provider.com@evil.com/x、http://api.provider.com/x、https://api.provider.com/x?y=1、https://api.provider.com:22/x、https://provider/x。 - 公网函数接受:
https://api.provider.com/v1/chat、https://API.Provider.COM:443/a/../v1(规范化为https://api.provider.com/v1)、https://api.provider.com:8443/x、https://xn--fsqu00a.xn--fiqs8s/x。 - 请求头
X-Yuyan-Request-ID为大写十六进制、35 位、含空格或路径分隔符:抛异常。 - 公网上游回 302:函数成功,状态码 302,
Location可读。 - 程序许可未声明通配来源:公网函数抛异常,且无请求发出。
边界
宿主不保证上游观察到取消或断开,只保证读取一方立即得到状态 3、不再拉取上游。本包不提供:选择多个流中先到者的原语;跨事件保存响应柄;名称解析结果的检查;HTTP/2 推送;自动重试;上游身份验证头(公网函数不许 Authorization)。宿主执行事件的总时限由宿主配置,本包只保证按给定期限令读取失败。