读取入站路径并向获授权服务转发原请求、按名筛头转发及以静态资源作答的公共接口。
源码浏览已生成;不能解析的文件以纯文本展示,不表示通过类型检查。
# 网页转发接口规范 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` 不受影响。
# 网页转发之约 0.4.0 宿主持一入站 HTTP 请,又得获授之服务绑定,方可具此包。请之法、原径及严解之径,另从[网页入站之约](../网页入站/规范.文言.md)取之;此包惟定转请与改址。 重定向入站请求,受单一 `/` 起首之绝对径,拒 `//`、反斜线、控制字与方案;合原协议域名及原查询,以三零八答,毋越外站。转发入站请求,先受获授绑定名,空名、越授权皆拒;后受新径,空则守原址,非空惟易路径,余查询、方法、正文流与头皆存。上游答之状态、头与正文流,直归来者,不先读,不截断。`ASSETS` 可指静资,其余名循授权服务表。 一入站请惟一终答;既设而复转,须报失。诸术同据此请,不得凭绑定名越权网联、持久对象或他请正文。绑定失则报调用失,传输错页由上层定。本包未定客之 HTTP 入口,仍从[网页服务之约](../网页服务/规范.文言.md)。 `转发入站请求并加标头` 循同绑定与改径之约,存上游状态、原头及正文流,惟覆所授之头,不先读正文。精确许 `Content-Security-Policy`、`X-Content-Type-Options`、`Referrer-Policy`、`Content-Type`、`Content-Disposition` 五名,至多八项;非法或重名则败。后二头之值由应用循白册定之;`Set-Cookie`、`Location`、`Content-Length` 等不得由此改之。此术亦占本请惟一终答。 ## 筛头转请(0.4.0 新增) `转发入站请求并筛标头 绑定名 新路径 保留名列 固定头列`(后二参之型为 `(列于字符串)` 与 `(列于(字符串合字符串))`)以当前请转于获授之 `SERVICE` 绑定,上游之答原样为此请之终答。 - **绑定名**:空名则败;未授之名或绑定不存在者,由宿主拒之,乃部署之误(宿主之异,客不可恃捕之)。静资之答用下节之 `回应入站以静态资源`,本术惟按 `SERVICE` 类寻之。 - **新径**(含查询):须单一 `/` 起首(次字节不得为 `/` 或 `\`),长一至八一九二字节,不含控字符、反斜线及 `#`,可含查询串。宿主以原请之源加新径成目标,故必不易其主机(「转发路径无效」)。 - **法与体**:转原请之法,许 GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS,余法则败(「转发方法不受支持」)。请体之流原样而转,不读不蓄(GET 与 HEAD 不带体);请体已被读则败(「入站请求正文已被读取,无法转发」);不随改址(`redirect: manual`),上游之三零几连同 `Location` 原样为终答。 - **头**:惟复 `保留名列` 所列之入站头(至多十六名;每名为一至六十四字节之令牌字;不辨大小写不得重;请中所无者略之),继叠 `固定头列`(至多十六项;值惟许可见 ASCII 与水平制表,至多八一九二字节;固定头覆同名之已复者;名不辨大小写不得重,故 `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 取之,不转原请之头与体。 - **状**:零者,沿用资源答之状;余者须在二百至五百九十九(「静态资源状态须为零或 200 至 599」)。 - **头**:以资源答之头为底,附加头逐名而处:列中某名初见之时,先去资源答中同名之头,再依序追加此名诸项;故可覆 `Cache-Control`,亦可增 `Set-Cookie`。附加头之名、值、数与禁名,其规同《网页答复》带头诸术(禁 `Content-Length`、`Transfer-Encoding`、`Connection`、`Keep-Alive`、`Upgrade`、`TE`、`Trailer`、`Content-Type`、`Content-Encoding`),资源自带之内容种类,客不得改。不暗增一头。 - **体**:资源答之正文流原样而授,不蓄。当前请为 HEAD 则不带正文,并废资源之正文流。若终状为二零四、二零五或三零四,而资源答带正文且请非 HEAD,则败(「该 HTTP 状态不得带静态资源正文」);资源答本无正文(如三零四)则如常沿用。 - **资源不存在**:ASSETS 常返四零四之答,此答如常为终答,客可以 `状` 参覆之。 - **败**:空绑定名、径、状、头不合规,为可捕之违约;ASSETS 之 `fetch` 报错则为可捕之事故(「读取静态资源失败:名: 辞」);未授之名或绑定不存在者,宿主拒之(部署之误)。 ## 一致之例 | 情 | 必见 | | --- | --- | | 筛头转 POST,留 `Authorization`、`X-Keep`,固定 `Cookie: a=b` | 上游惟见此数头与固定头,法为 POST,径为新径,请体原样,`redirect` 为 manual | | 同转而用 HEAD、PUT、PATCH、DELETE、OPTIONS | 法原样;GET、HEAD 之上游无请体 | | 上游返三零二与 `Location` | 终答即此三零二,不发第二请 | | 保留名含 `Host` 或 `transfer-encoding`,或固定头含二 `Cookie` | 违约 | | 新径 `//evil.example`、`/a\b`、`/a#b`、含 CR LF | 违约 | | 请体分二块,第二块须俟上游读毕首块而后生 | 转发成(证其未蓄) | | 静资,状零,附 `Cache-Control: no-store`、`X-New: 1` | 沿资源之状;`Cache-Control` 被覆,`X-New` 被增,`Content-Type` 守资源之原 | | 静资 HEAD | 状与头如常,正文空,资源正文流被废 | | 静资状二零四而资源有正文(GET) | 违约 | ## 所不为 此包不析不改请体,不重试,不转于未授之绑定,不供出站网络,不暗增或转发头(除非列入保留名或固定头),亦不缓存资源。 ## 补:点段之径一律拒之(独立审后修订) 转发之径与静态资源之径,其任一段为 `.` 或 `..`(含 `%2e` 大小写混写之形,后随 `/`、`?` 或径末)者,依「转发路径无效」「静态资源路径无效」拒之:WHATWG URL 之析必折叠此等段,使 `/public/../secret/s.txt` 越出所授之前缀。形似而非点段者(`...`、`..b`、`.b`、`b..c`)不与焉。