网页事件源之约 0.1.0
此包令浏览器中豫言之客读同源之服务器推事流(Server-Sent Events,text/event-stream)。较浏览器原生之 EventSource,有二处刻意之异:其一,事不逐条回调,而成批入统一事列(见[网页事件之约](../网页事件/规范.文言.md)),一回放数千条旧事,亦仅生少数列事;其二,宿主依客处事之缓急而读网流,列中积压过多则止读(以 HTTP 流控传压于服务器),故不失一消息——原生 EventSource 与统一事列之弃法皆不能也。服务端之事件流应,见[网页事件流](../网页事件流/规范.文言.md)。客依此包,诸术皆当具。
联之行
宿主依 WHATWG SSE 之规解其应,并复 EventSource 之重连:
- 请求头带
Accept: text/event-stream与Cache-Control: no-cache,credentials: 'same-origin';已知末事件号则带Last-Event-ID(初连用选项之“起始事件号”,其后用流中最近所收之id:)。 - 惟 HTTP 二百 且 Content-Type 为 text/event-stream(略参数与大小写)方为连成。他状态(含二百零四)与类型不合,皆致命之错:投“错误”(“已关闭”)后不复重连,亦不复有事。
- 流正终或网中断,则投“错误”(“重连中”),候重连之间而自重连,成则再投“打开”;重连之间初为选项“重连毫秒”(默认三千),服务器发
retry:则从之(限一百至六万毫秒)。 - 事依 SSE 之规而切:
data:多行以换行连之;event:定事名(默认 message);id:更新“末事件号”(含 NUL 者略之),每事带其发时之末事件号;空 data 不生事;注释行(“:”首)略之;行终可为\n、\r、\r\n;流首之 BOM 略之;无效 UTF-8 字节依浏览器之规易为 U+FFFD。 - 单事之数逾一 MiB 者为致命之错(“已关闭”,因“事件过大”)。
诸术
打开事件源:字符串(网址)、字符串(选项),返整数
网址之律同网页请求包(“/”首之站内径,或同源绝对网址;至多八千一百九十二码元;无控制字符与反斜杠)。选项乃癸象对象,可为空文(视同 {});字段:
| 字段 | 类型与默认 | 律 | | --- | --- | --- | | 起始事件号 | 文,默认无 | 至多二百五十六 UTF-16 码元,无换行与 NUL;初连以为 Last-Event-ID,用于自游标续读(如前所读至之号) | | 重连毫秒 | 整数,默认三千 | 一百至六万;重连间之初值 |
未知字段、类型不合、网址非同源、同时已有八个事件源,皆发事故。返事件源号(正整数,实例内递增,不复用);联于后台立。
关闭事件源:整数,返爻
止事件源并去其未取之事。事件源仍在(含候重连中),或有未取之事被去,则返阳;号未知,或已因致命之错自闭而事已取尽,则返阴。既闭,保证不复收此号之事。
事
类曰“事件流”,订阅号即事件源号,名与详情如下(余字段依网页事件之约):
| 名 | 详情 | 义 |
| --- | --- | --- |
| 打开 | {"重连":爻} | 联成;“重连”于首连之后为阳 |
| 消息 | {"批":[{"事件号":"12","事件名":"message","数据":"…"},…]} | 一批之事,一至二百五十六项,依到达之序;一批之数据总量至多约一 MiB(单事更大则自成一批) |
| 错误 | {"状态":"重连中"或"已关闭","原因":文,"HTTP状态":整数(可省)} | 联断;“重连中”后宿主自重连(成则有新“打开”),“已关闭”后此事件源终 |
“原因”有:服务端关闭(流正终)、网络中断(连不通、读流出错,含重定向至他来源——mode: same-origin 视作网络之错,依重连之间而复试)、HTTP 状态 N(附 HTTP状态)、内容类型不是 text/event-stream、事件过大。同一事件源之事保先后:打开 → 若干消息 → 错误 → 打开 → …。客处消息批,逐取 批[i],并自以事件号(如业务中递增之号)去重——重连或重放少许已见之事。
背压:宿主于每事件源,列中此源未取之事多于八,则止读网流,待客取后复续;止时服务器一侧之写按 HTTP 流控受阻(服务端可用[网页事件流](../网页事件流/规范.文言.md)包之背压感知以相配)。事类“事件流”之列限默认一千零二十四,背压保积压远低于此,不触发弃。客久不取事,则联持止而非失消息。
限额与败之类
| 项 | 限 | | --- | --- | | 同时之事件源 | 八 | | 单事之数据 | 一 MiB | | 一批之事 | 二百五十六项且约一 MiB | | 未取之事(每事件源) | 约八批(背压之阈) | | 网址 | 八千一百九十二 UTF-16 码元 |
违约之调用(网址不合或非同源、选项无效、事件源已满、宿主已闭)发豫言事故;联与流之运行时败,以“错误”事报之,不发事故。
一致性之例
- 服务器依次发
id:1 data:a、id:2 event:x data:b:客先得“打开”,再得一“消息”事,“批”为[{"事件号":"1","事件名":"message","数据":"a"},{"事件号":"2","事件名":"x","数据":"b"}](同一到达之窗并为一批亦合法)。 - 服务器发 data 二行“第一”“第二”:一事,数据“第一\n第二”。
- 服务器三秒内闭联:客得“错误”(“重连中”,“服务端关闭”),随后自重连,服务器收
Last-Event-ID: 2,客得新“打开”(“重连”为阳)。 - 服务器返四百零四:客得“错误”(“已关闭”,“HTTP 状态 404”),不复重连;返 text/html:“已关闭”,因内容类型。
- 服务器一回放五千事而客暂不取:列中“事件流”事不逾约八批,联被止;客取后续收,终五千条无失无重。
- 关闭事件源之后,虽网中犹有数据,亦不复有此号之事;同时开第九个事件源发事故。
界
此包不定:跨来源事件流(CORS)、自定请求头与 POST 之事件流、fetch 流之通用读取、WebSocket、事件流之服务端写入(见网页事件流包)、断线期间之排队与离线缓存。