豫言 / 豫言操作系统网页请求 @ 0.1.0

向同源发起非阻塞的网页请求,结果作为事件进入统一事件队列,可取消;另附阻塞变体。

源码浏览已生成;不能解析的文件以纯文本展示,不表示通过类型检查。

规范.汉语.md

# 网页请求接口规范 0.1.0

本包让浏览器里的豫言应用向**本站(同源)**发起 HTTP 请求并读取文字响应。它是 `fetch` 的最小公共子集,为豫言的单事件循环而设计:**发起请求不阻塞**——`发起网页请求` 立即返回请求号,请求在后台进行,结束时宿主向统一事件队列(见[网页事件接口规范](../网页事件/规范.汉语.md))投递一个类型为“请求”的事件;多个请求可以同时在途,应用继续处理界面事件,也可以随时 `取消网页请求`。为方便简单场景另附阻塞变体 `请求网页文字`。应用依赖本包后,全部函数都必须实现。

出站到其他来源的请求、服务端的出站请求分别属于[网络](../网络/规范.汉语.md)(整体请求响应,暂无浏览器适配)与网页上游、授权服务等包,不在本包。

## 请求 JSON

`发起网页请求`、`请求网页文字` 的参数是 JSON 对象,**只有 `网址` 必填**,其余可省;出现未知字段或类型不对一律抛事故。

| 字段 | 类型与默认 | 规则 |
| --- | --- | --- |
| `网址` | 文字,必填 | 以 `/` 开头(不以 `//` 开头)的站内路径,或与当前页面**同源**的绝对网址;至多 8192 个 UTF-16 码元;不含控制字符与反斜杠。片段(`#…`)被忽略 |
| `方法` | 文字,默认 `GET` | 只能是 `GET`、`HEAD`、`POST`、`PUT`、`PATCH`、`DELETE`(大写) |
| `标头` | 对象,默认无 | 名称→文字值;至多 32 项;名称 1 至 64 个 ASCII 字母、数字、连字符;值至多 4096 个 UTF-16 码元且不含控制字符;宿主拒绝 fetch 规范的禁用标头名(`Cookie`、`Host`、`Content-Length`、`Origin`、`Referer`、`User-Agent`、`Connection`、`Transfer-Encoding`、`Upgrade`、`Via`、`Accept-Encoding`、`Date`、`Expect` 以及 `Sec-`、`Proxy-` 前缀) |
| `正文` | 文字,默认无 | 请求正文,按 UTF-8 发送;至多 8 MiB(UTF-8 字节);`GET`、`HEAD` 带正文属违规。带 `正文` 而 `标头` 里没有 `Content-Type` 时宿主不加默认值,应用应自己写(例如 `application/json`) |
| `缓存` | 文字,默认 `默认` | `默认` 用浏览器默认缓存策略;`不缓存` 等价于 `cache: 'no-store'` |
| `超时毫秒` | 整数,默认 60000 | 1 至 600000;从发出到读完正文的总时限 |
| `正文上限` | 整数,默认 8388608 | 1 至 16777216(字节);响应正文超过此值即中止并报“正文过大” |
| `标记` | 文字,默认空 | 至多 256 个 UTF-16 码元;原样出现在响应里,供应用配对请求 |

宿主固定使用 `credentials: 'same-origin'`(带本站的饼)与 `mode: 'same-origin'`(重定向到别的来源即视为网络错误),跟随同源重定向。请求 JSON 整体至多 10 MiB。

## 响应 JSON

事件详情与阻塞变体的返回值是同一种对象:

```json
{"成":true,"状态":200,"状态文":"OK","网址":"https://例.站/cloud/api/session",
 "标头":{"content-type":"application/json","cache-control":"no-store"},
 "正文":"{\"user\":…}","字节数":1234,"标记":"会话"}
```

```json
{"成":false,"原因":"超时","说明":"请求超过 60000 毫秒未完成","标记":"会话"}
```

- **成为真**:收到了 HTTP 响应并读完正文;**任何状态码(含 4xx、5xx)都是“成”**,应用自行判断 `状态`。`网址` 是跟随重定向后的最终网址;`标头` 的名称一律小写,同名多值以 `, ` 连接,`Set-Cookie` 不可见;`正文` 是响应体按**严格 UTF-8**解码的文字(`HEAD` 与 204、205 响应为空文字);`字节数` 是响应体的字节数。
- **成为假**:`原因` 只有四种——`网络错误`(连接失败、被重定向到别的来源、被浏览器拒绝等)、`超时`、`正文过大`、`正文不是有效UTF-8`;`说明` 是中文说明。
- 两种对象都带 `标记`(省略时为空文字)。

## 函数

### `发起网页请求 : 字符串 → 整数`

校验请求 JSON 后立即返回请求号(正整数,实例内单调递增,不复用),请求在后台进行。结束时投递一个事件:类型 `请求`,`订阅号` = 请求号,`名称` 为 `完成`(成为真)或 `失败`(成为假),`详情` 为响应 JSON。同时“在途或结果尚未被应用取走”的请求至多 32 个(含阻塞变体的请求),已达上限时抛事故——应用应把并发控制在自己的状态机里,并及时取走结果事件。

### `取消网页请求 : 整数 → 爻`

取消一个请求。请求仍在进行,或它的结果事件还在队列里没被取走时,中止请求、移除该事件并返回阳;请求号未知,或结果事件已经被应用取走时返回阴。**取消之后保证不再收到该请求号的事件**,因此应用可以把“旧请求的响应不得覆盖新状态”这类竞态用取消或世代号解决。

### `请求网页文字 : 字符串 → 字符串`

阻塞变体:参数同 `发起网页请求`,挂起当前调用,直到请求结束,返回响应 JSON。**等待期间其他事件照常进入队列**,但应用在这次调用返回之前不会处理它们,因此只适合启动时的一次性读取或明确希望串行的场景;需要并发或可取消的请求用 `发起网页请求`。违规调用抛事故,网络类失败归入响应(成为假),不抛事故。阻塞变体不可取消,不产生事件,也占用并发名额。

## 事件

`等待网页事件` 返回的事件 JSON 形如

```json
{"类型":"请求","序":42,"订阅号":7,"名称":"完成","详情":{"成":true,"状态":200,…}}
```

“请求”类型的事件队列独立计数,默认上限 1024;并发上限 32(含结果未取走的请求)保证不会因积压而丢失结果。

## 限额与失败分类

| 项 | 限额 |
| --- | --- |
| 并发在途请求(含结果尚未取走者) | 32 |
| 请求 JSON | 10 MiB;请求正文 8 MiB;网址 8192 码元;标头 32 项 |
| 响应正文 | 默认 8 MiB,可配至 16 MiB |
| 超时 | 默认 60 秒,可配 1 毫秒至 10 分钟 |

- **违规调用**(请求 JSON 无效、字段未知或越界、网址非同源、并发已满、宿主已关闭)抛豫言事故,消息为中文并指出出错字段。
- **运行时失败**(网络错误、超时、正文过大、正文不是有效 UTF-8)是响应的一种,`成` 为假,不抛事故。
- **取消**不产生任何事件。

## 一致性样例

1. `发起网页请求({"网址":"/api/甲","标记":"a"})` 返回 1;`等待网页事件` 得类型 `请求`、订阅号 1、名称 `完成`、详情 `状态` 为 200、`标记` 为 `a`、`正文` 为服务器返回的文字。
2. 服务器返回 404 与 JSON 错误体:仍是 `完成`,`状态` 为 404,`正文` 含错误体。
3. 三个请求同时发起,服务器按相反顺序返回:三个事件按到达顺序进入队列,各自订阅号不同。
4. 发起后立即 `取消网页请求`:返回阳,之后队列里没有该请求号的事件。
5. 服务器断开连接:`失败`,`原因` 为 `网络错误`;响应体含无效 UTF-8 字节:`失败`,`原因` 为 `正文不是有效UTF-8`。
6. `网址` 为 `https://别处.站/x`:抛事故(非同源);第 33 个并发请求:抛事故。
7. `请求网页文字` 对 `/api/甲` 返回响应 JSON,等待期间到达的点击事件仍在队列里,返回后可取到。

## 边界

本包不规定:跨来源请求(CORS)、请求与响应的流式读写(服务端事件流见网页事件源包)、二进制正文与文件上传、进度事件、`FormData`、Service Worker、HTTP 缓存细节、`fetch` 的 `keepalive` 与优先级。

规范.文言.md

# 网页请求之约 0.1.0

此包令浏览器中豫言之客,向**本站(同源)**发 HTTP 请求而读其文字之应。乃 fetch 之至简公共子集,为豫言单事环而设:**发请求不候**——发起网页请求立返请求号,请求于后台行,毕则宿主投类曰“请求”之事于统一事列(见[网页事件之约](../网页事件/规范.文言.md));多请求可同时在途,客仍可理界面之事,亦可随时取消网页请求。为简易之场,另附阻塞之变体请求网页文字。客依此包,诸术皆当具。

发往他来源之请求,及服务端之出站请求,分属[网络](../网络/规范.文言.md)(整体请求与应,暂无浏览器适配)与网页上游、授权服务等包,不在此包。

## 请求之癸象文

发起网页请求、请求网页文字之参数乃癸象对象,**惟“网址”必填**,余皆可省;出未知字段或类型不合,一概发事故。

| 字段 | 类型与默认 | 律 |
| --- | --- | --- |
| 网址 | 文,必填 | 以“/”首(非“//”首)之站内径,或与当前页**同源**之绝对网址;至多八千一百九十二 UTF-16 码元;无控制字符与反斜杠;片段(“#…”)略之 |
| 方法 | 文,默认 GET | 惟 GET、HEAD、POST、PUT、PATCH、DELETE(大写) |
| 标头 | 对象,默认无 | 名至值文;至多三十二项;名一至六十四个 ASCII 字母、数字、连字符;值至多四千零九十六码元而无控制字符;宿主拒 fetch 规范所禁之标头名(Cookie、Host、Content-Length、Origin、Referer、User-Agent、Connection、Transfer-Encoding、Upgrade、Via、Accept-Encoding、Date、Expect 及 Sec-、Proxy- 之首) |
| 正文 | 文,默认无 | 请求之体,依 UTF-8 而发;至多八 MiB(UTF-8 字节);GET、HEAD 带正文则违约。有正文而标头无 Content-Type,宿主不代为添,客当自书(如 application/json) |
| 缓存 | 文,默认“默认” | “默认”依浏览器缓存之策;“不缓存”等于 cache: 'no-store' |
| 超时毫秒 | 整数,默认六万 | 一至六十万;自发至读毕正文之总限 |
| 正文上限 | 整数,默认八三八八六零八 | 一至一千六百七十七万七千二百一十六(字节);应之体逾此则中止而报“正文过大” |
| 标记 | 文,默认空 | 至多二百五十六码元;原样见于响应,供客配请求 |

宿主恒用 credentials: 'same-origin'(带本站之饼)与 mode: 'same-origin'(重定向至他来源即视为网络之错),随同源之重定向。请求癸象文整体至多十 MiB。

## 响应之癸象文

事详情与阻塞变体之返值乃同一形:

```json
{"成":true,"状态":200,"状态文":"OK","网址":"https://例.站/cloud/api/session",
 "标头":{"content-type":"application/json","cache-control":"no-store"},
 "正文":"{\"user\":…}","字节数":1234,"标记":"会话"}
```

```json
{"成":false,"原因":"超时","说明":"请求超过 60000 毫秒未完成","标记":"会话"}
```

- **成为真**:得 HTTP 之应而读毕其体;**任何状态码(含四百、五百)皆为“成”**,客自察“状态”。“网址”乃随重定向后之终址;“标头”名一概小写,同名多值以“, ”连之,Set-Cookie 不可见;“正文”乃应体依**严格 UTF-8**所解之文(HEAD 与二百零四、二百零五之应为空文);“字节数”乃应体之字节数。
- **成为假**:“原因”惟四种——“网络错误”(连不通、重定向至他来源、为浏览器所拒等)、“超时”、“正文过大”、“正文不是有效UTF-8”;“说明”乃中文之释。
- 二形皆带“标记”(省则空文)。

## 诸术

### 发起网页请求:字符串,返整数

验请求癸象文后立返请求号(正整数,实例内递增,不复用),请求于后台行。毕则投一事:类曰请求,订阅号即请求号,名曰“完成”(成为真)或“失败”(成为假),详情为响应癸象。同时“在途或果尚未被客取”者至多三十二(含阻塞变体之请求),已至限则发事故——客当以己之状态机控其并发,并速取其果之事。

### 取消网页请求:整数,返爻

撤一请求。请求仍在行,或其结果之事尚在列而未取,则止其请求、去其事而返阳;号未知,或结果之事已被客取,则返阴。**既撤,保证不复收此号之事**,故客可以撤请求或世代号解“旧请求之应不得覆新态”之争。

### 请求网页文字:字符串,返字符串

阻塞变体:参数同发起网页请求,挂起当前调用,候请求毕,返响应癸象。**候时他事照常入列**,然客于此调返回前不理之,故惟宜启动时之一读,或明欲串行之场;欲并发或可撤者,用发起网页请求。违约之调用发事故;网络类之败归入响应(成为假),不发事故。阻塞变体不可撤,不生事,亦占并发之额。

## 事

等待网页事件所返之事癸象形如

```json
{"类型":"请求","序":42,"订阅号":7,"名称":"完成","详情":{"成":true,"状态":200,…}}
```

“请求”类之事列自计其数,默认限一千零二十四;并发之限三十二(含果未取之请求),保结果不因积压而失。

## 限额与败之类

| 项 | 限 |
| --- | --- |
| 并发在途之请求(含果未取者) | 三十二 |
| 请求癸象文 | 十 MiB;请求正文八 MiB;网址八千一百九十二码元;标头三十二项 |
| 应体 | 默认八 MiB,可配至十六 MiB |
| 超时 | 默认六十秒,可配一毫秒至十分钟 |

- **违约之调用**(请求癸象文无效、字段未知或越界、网址非同源、并发已满、宿主已闭)发豫言事故,辞为中文而指其出错之字段。
- **运行时之败**(网络错误、超时、正文过大、正文非有效 UTF-8)乃响应之一种,“成”为假,不发事故。
- **撤**则不生任何事。

## 一致性之例

1. 发起网页请求({“网址”:“/api/甲”,“标记”:“a”})返一;等待网页事件得类请求、订阅号一、名完成、详情状态二百、标记“a”、正文为服务器所返之文。
2. 服务器返四百零四与癸象错体:仍为完成,状态四百零四,正文含错体。
3. 三请求同发,服务器反序而返:三事依到达之序入列,订阅号各异。
4. 发起后旋即取消网页请求:返阳,其后列中无此号之事。
5. 服务器断连:失败,原因“网络错误”;应体含无效 UTF-8 字节:失败,原因“正文不是有效UTF-8”。
6. 网址为 `https://别处.站/x`:发事故(非同源);第三十三个并发请求:发事故。
7. 请求网页文字于 /api/甲 返响应癸象,候时所至之点击事仍在列,返后可取。

## 界

此包不定:跨来源请求(CORS)、请求与应之流式读写(服务端事件流见网页事件源包)、二进制正文与文件上传、进度事、FormData、Service Worker、HTTP 缓存之细、fetch 之 keepalive 与优先级。