跳到正文
豫言包管理
← 全部包

豫言操作系统网页转发 0.4.0

豫言 · 库

读取入站路径并向获授权服务转发原请求、按名筛头转发及以静态资源作答的公共接口。

网页转发接口规范 0.4.0

本包用于持有一个入站 HTTP 请求、可访问获授权服务绑定的宿主。请求方法、原路径和严格解码路径由独立的[网页入站包](../网页入站/规范.汉语.md)读取;本包只决定如何转发或重定向。

重定向入站请求 接受以单个 / 开头的绝对路径,拒绝 //、反斜线、控制字符与 URL 方案。宿主以原请求的协议和域名构造地址,保留原查询串,返回状态 308;不得转往外站。转发入站请求 的第一参数是获授权绑定名,空名或未授权名须失败。第二参数为空字符串时保留原请求 URL;非空时只改路径,规则与重定向路径相同,原查询、方法、正文流和标头保持原样。绑定请求的响应状态、标头和正文流应直接传回调用方,不额外读取或截断。宿主可把特殊名 ASSETS 绑定到静态资源,其余名称按授权服务表解析。

每次入站调用只能成功设置一次最终响应;之后再调用重定向或转发须失败。宿主须确保同一请求内的操作使用同一请求实例,不能借绑定名访问未授权网络、持久对象或另一个请求的正文。目标绑定失败时报告调用失败;具体传输错误页由上层服务决定。本包不实现应用提供的 HTTP 处理入口,入口契约仍在[网页服务包](../网页服务/规范.汉语.md)。

转发入站请求并加标头 的绑定与路径规则同 转发入站请求。它复制上游状态、正文流和原有响应头,仅覆盖参数列表给出的响应头;不读取或缓冲正文。允许精确名称 Content-Security-Policy、X-Content-Type-Options、Referrer-Policy、Content-Type 和 Content-Disposition,最多 8 项,非法或重复名称失败。Content-Type 和 Content-Disposition 的值由应用按已允许资源决定;应用不能借此改写 Set-Cookie、Location、Content-Length 等协议或身份标头。此操作同样占用本次请求唯一的最终响应。

筛头转发(0.4.0 新增)

转发入站请求并筛标头 绑定名 新路径 保留名列 固定头列(后两个参数分别是 (列于字符串) 与 (列于(字符串合字符串)))把当前请求转给获授权的 SERVICE 绑定,上游响应原样成为本次最终响应。

  • 绑定名:空名失败;未授权名或不存在的绑定由宿主拒绝,属于部署错误(宿主异常,应用不能依赖捕获)。静态资源用下一节的 回应入站以静态资源,本函数只按 SERVICE 类查找。
  • 新路径(含查询):须以单个 / 起首(第二个字节不得是 / 或 \),长度 1 至 8192 字节,不含控制字符、反斜线与 #,可含查询串。宿主用原请求的来源加新路径构造目标,因此绝不会改变主机(“转发路径无效”)。
  • 方法与正文:转发原请求的方法,允许 GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS,其他方法失败(“转发方法不受支持”)。请求体流原样转发,不读取、不缓冲(GET 与 HEAD 不带体);请求体已被读取时失败(“入站请求正文已被读取,无法转发”);不跟随重定向(redirect: manual),上游的 3xx 连同 Location 按原样成为最终响应。
  • 标头:只复制 保留名列 列出的入站标头(最多 16 个名称;每个名称是 1 至 64 字节的令牌字符;不分大小写不得重复;请求里缺失的标头略过),然后叠加 固定头列(最多 16 项;值只允许可见 ASCII 与水平制表,至多 8192 字节;固定标头覆盖同名的已复制标头;名称不分大小写不得重复,因此至多出现一个 Cookie)。宿主管理的名称不得保留或固定:Host、Connection、Keep-Alive、Proxy-Connection、Proxy-Authorization、TE、Trailer、Transfer-Encoding、Upgrade、Expect;固定标头还不得设置 Content-Length 与 Set-Cookie;Content-Length、Content-Type 等可以列入保留名列原样复制。所复制的入站标头值若含控制字符(水平制表除外)则拒绝转发。
  • 响应:上游响应的状态、标头与正文流原样成为最终响应,不读取、不缓冲;正文的首块可在上游尚未产出后续块时先到达调用方。
  • 上游失败:服务绑定的 fetch 抛出时,转为可捕获的豫言异常(“转发到服务失败:名称: 消息”),应用可改答错误页。

违规(可捕获的豫言异常,此时不产生响应):空绑定名、路径无效、保留名或固定头过多或无效、重名、禁用名、固定头值无效、方法不受支持、入站正文已读、入站标头值含控制字符。

静态资源作答(0.4.0 新增)

回应入站以静态资源 绑定名 路径 状态 附加头列(状态是整数,附加头列是 (列于(字符串合字符串)))从获授权的 ASSETS 绑定读取路径并作为本次最终响应。

  • 路径:规则同筛头转发的新路径,宿主以原请求的来源加路径构造目标,按 GET 读取,不转发原请求的标头或正文。
  • 状态:0 表示沿用资源响应的状态;否则须在 200 至 599(“静态资源状态须为零或 200 至 599”)。
  • 标头:以资源响应的标头为底,附加标头逐名处理:列表里某个名称第一次出现时,先删除资源响应里的同名标头,再按列表顺序追加该名称的各项;因此既可覆盖 Cache-Control,也可追加 Set-Cookie。附加标头的名称、值、数量与禁用名规则同《网页答复》带头系列(禁 Content-Length、Transfer-Encoding、Connection、Keep-Alive、Upgrade、TE、Trailer、Content-Type、Content-Encoding),资源自带的内容类型因此不能被应用改写。不隐式添加任何标头。
  • 正文:资源响应的正文流原样交付,不缓冲。当前请求是 HEAD 时不带正文,并取消资源正文流。若最终状态是 204、205 或 304,而资源响应带正文且请求不是 HEAD,失败(“该 HTTP 状态不得带静态资源正文”);资源响应本身无正文时(如 304)照常沿用。
  • 资源不存在:ASSETS 通常返回 404 响应,它照常成为最终响应,应用可用 状态 参数覆盖。
  • 失败:空绑定名、路径或状态或标头不合规,是可捕获的违规;ASSETS 的 fetch 抛出时是可捕获的豫言异常(“读取静态资源失败:名称: 消息”);未授权名或不存在的绑定由宿主拒绝(部署错误)。

一致性样例

| 情境 | 必须观察到 | | --- | --- | | 筛头转发 POST,保留 Authorization、X-Keep,固定 Cookie: a=b | 上游只看到这几个标头与固定头,方法为 POST,路径为新路径,请求体原样,redirect 为 manual | | 同一转发用 HEAD、PUT、PATCH、DELETE、OPTIONS | 方法原样;GET、HEAD 上游没有请求体 | | 上游返回 302 与 Location | 最终响应就是这个 302,不发第二次请求 | | 保留名含 Host 或 transfer-encoding,或固定头含两个 Cookie | 违规 | | 新路径 //evil.example、/a\b、/a#b、含 CR LF | 违规 | | 请求体分两块,第二块要在上游读完第一块之后才产生 | 转发成功(证明没有缓冲) | | 静态资源,状态 0,附加 Cache-Control: no-store、X-New: 1 | 沿用资源状态;Cache-Control 被覆盖,X-New 被追加,Content-Type 保持资源原值 | | 静态资源 HEAD | 状态与标头照旧,正文为空,资源正文流被取消 | | 静态资源状态 204 且资源有正文(GET) | 违规 |

不做什么

本包不解析或改写请求体,不重试,不转发到未授权绑定,不提供出站网络访问,不隐式添加或转发标头(除非列入保留名或固定头),也不缓存资源。

补充:点段路径一律拒绝(独立审查后修订)

转发路径与静态资源路径中任一段是 . 或 ..(包括 %2e 的任意大小写混写形式,后接 /、? 或路径结尾)时,按「转发路径无效」「静态资源路径无效」拒绝:WHATWG URL 解析会折叠这些段,使 /public/../secret/s.txt 越出授权前缀。形似而非点段的 ...、..b、.b、b..c 不受影响。

依赖

查看包配置

上传历史

当前上传修订:1 ·

  1. 上传修订 1
    下载 ZIP

包层级

父包:豫言操作系统接口

没有子包。