@plurnk/plurnk-schemes-http 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.defaults +4 -0
- package/README.md +2 -2
- package/SPEC.md +30 -4
- package/dist/Browser.d.ts +12 -3
- package/dist/Browser.d.ts.map +1 -1
- package/dist/Browser.js +23 -16
- package/dist/Browser.js.map +1 -1
- package/dist/Guard.d.ts +14 -0
- package/dist/Guard.d.ts.map +1 -0
- package/dist/Guard.js +108 -0
- package/dist/Guard.js.map +1 -0
- package/dist/Http.d.ts +1 -1
- package/dist/Http.d.ts.map +1 -1
- package/dist/Http.js +53 -4
- package/dist/Http.js.map +1 -1
- package/dist/WebFetcher.d.ts +21 -0
- package/dist/WebFetcher.d.ts.map +1 -0
- package/dist/WebFetcher.js +63 -0
- package/dist/WebFetcher.js.map +1 -0
- package/dist/Ws.d.ts +23 -0
- package/dist/Ws.d.ts.map +1 -0
- package/dist/Ws.js +158 -0
- package/dist/Ws.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/docs/http.md +2 -0
- package/docs/wss.md +45 -0
- package/package.json +12 -3
package/.env.defaults
CHANGED
|
@@ -31,6 +31,10 @@ PLURNK_SCHEMES_HTTP_MOBILE=1
|
|
|
31
31
|
# window — every read revalidates via ETag/304 (the always-fresh default).
|
|
32
32
|
# Required read: unset crashes, naming the var.
|
|
33
33
|
PLURNK_SCHEMES_HTTP_TTL_MS=0
|
|
34
|
+
# Max HTTP redirect hops the SSRF-guarded fetch follows (WebFetcher). Each hop is
|
|
35
|
+
# re-guarded — a public URL redirecting into private space is refused. 0 follows
|
|
36
|
+
# none (strictest). Required read: unset crashes, naming the var.
|
|
37
|
+
PLURNK_SCHEMES_HTTP_REDIRECTS=5
|
|
34
38
|
|
|
35
39
|
# ── Optional modes (absence IS the mode — never floor-set) ──────────────────
|
|
36
40
|
# Remote CDP endpoint (shared chromium / Lightpanda / browserless). Unset →
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# plurnk-schemes-http
|
|
2
2
|
|
|
3
|
-
`http(s)://` URI scheme handler for the [plurnk](https://github.com/plurnk/plurnk-service) agent runtime. The **first greenfield `@plurnk/plurnk-schemes-*` sibling** — authored entirely against the DB-free capability contract ([`@plurnk/plurnk-schemes`](https://github.com/plurnk/plurnk-schemes) `SchemeCtx`), importing zero plurnk-service internals.
|
|
3
|
+
`http(s)://` URI scheme handler for the [plurnk](https://github.com/plurnk/plurnk-service) agent runtime. The **first greenfield `@plurnk/plurnk-schemes-*` sibling** — authored entirely against the DB-free capability contract ([`@plurnk/plurnk-schemes`](https://github.com/plurnk/plurnk-service/tree/main/plurnk-schemes) `SchemeCtx`), importing zero plurnk-service internals.
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ Response status + headers land in the `header` channel; the body in `body` (the
|
|
|
22
22
|
|
|
23
23
|
## Design
|
|
24
24
|
|
|
25
|
-
- **Streaming via the capability `subscriptions` lifecycle** (`open` → `notifyChunk` → `close`). `open()` returns the
|
|
25
|
+
- **Streaming via the capability `subscriptions` lifecycle** (`open` → `notifyChunk` → `close`). `open()` returns the worker+teardown-composed `AbortSignal`; a `SubscriptionHandle` is registered so the engine routes `SEND[499]` cancellation to the in-flight `fetch`.
|
|
26
26
|
- **No runtime dependencies** — `fetch`, `AbortController`, `TextDecoder`, `ReadableStream` are Node ≥25 built-ins.
|
|
27
27
|
- **DB-free** — reaches the substrate only through `ctx` capabilities (`subscriptions`, `entries`), never a raw DB handle (plurnk-schemes SPEC §5). This is what the keystone capability ctx made possible.
|
|
28
28
|
|
package/SPEC.md
CHANGED
|
@@ -13,7 +13,7 @@ static manifest: SchemeManifest = {
|
|
|
13
13
|
channels: { body: "application/octet-stream", header: "text/plain" },
|
|
14
14
|
defaultChannel: "body",
|
|
15
15
|
category: "data",
|
|
16
|
-
scope: "
|
|
16
|
+
scope: "workspace",
|
|
17
17
|
writableBy: ["model", "client"],
|
|
18
18
|
volatile: true, // remote content can change between fetches
|
|
19
19
|
modelVisible: true,
|
|
@@ -37,9 +37,9 @@ Results use the `passthrough` family (read-only / network shape) — http entrie
|
|
|
37
37
|
|
|
38
38
|
All verbs share one streaming core:
|
|
39
39
|
|
|
40
|
-
1. `ctx.subscriptions.open(pathname, handle)` — registers the subscription for cancel routing; returns the
|
|
40
|
+
1. `ctx.subscriptions.open(pathname, handle)` — registers the subscription for cancel routing; returns the worker+teardown-composed `AbortSignal`. The handle's `cancel()` aborts a local `AbortController` wired to the `fetch`/render.
|
|
41
41
|
2. `fetch(url, { signal })` — GET (READ) or POST (SEND[200], body from `SendBody.raw`); read the response `Content-Type`.
|
|
42
|
-
3. **Render gate ({§render-lifecycle}):** a GET whose response is HTML routes to the render path; everything else (POST responses, non-HTML bodies) streams raw.
|
|
42
|
+
3. **Render gate ({§render-lifecycle}):** a GET whose response is HTML routes to the render path; a GET whose response is `text/event-stream` routes to the SSE path ({§sse}); everything else (POST responses, non-HTML bodies) streams raw.
|
|
43
43
|
4. Response status + headers → `notifyChunk("header", …, "text/plain")`.
|
|
44
44
|
5. Body → `notifyChunk("body", chunk, mimetype)` — labelled with its real type (the response Content-Type, or `text/html` rendered). Byte path streams chunks as they arrive; render path writes the serialized DOM in one chunk.
|
|
45
45
|
6. `close("done", …)` on clean end; `close("error", reason)` on failure.
|
|
@@ -71,9 +71,35 @@ The **render path** takes one runtime dependency, `playwright`, **lazy-imported*
|
|
|
71
71
|
`Browser` (`export default class`, barrel-exported as a standalone foundation) is the headless-Chromium render engine — ported from rummy.web's WebFetcher, render-only.
|
|
72
72
|
|
|
73
73
|
- **Gate:** a GET whose response `Content-Type` is `text/html` / `application/xhtml+xml` renders; the probe-fetch body is discarded and the browser does its own navigation. POST never renders.
|
|
74
|
-
- **Render:** warm chromium (one per `Browser`), per-
|
|
74
|
+
- **Render:** warm chromium (one per `Browser`), per-worker `BrowserContext` keyed on `ctx.workerId`, **mobile-emulated by default** (Pixel-5-class viewport + UA — responsive sites serve lighter layouts; `PLURNK_SCHEMES_HTTP_MOBILE=0` renders desktop), navigate with `waitUntil: "networkidle"` + a salvage path (timed-out-but-rendered pages with substantive body text), serialize the final DOM via `page.content()`.
|
|
75
75
|
- **Body:** the serialized DOM is delivered as one `body` chunk labelled `text/html`; the mimetype layer projects everything (`content`/`symbols`/`deepXml`/embedding) off it. http never cleans or extracts — the body is the faithful, final page (schemes-http#1).
|
|
76
76
|
- **Host rewrite (bounded, first-party):** {§host-rewrite} a GitHub `…/blob/…` URL is fetched as its `raw.githubusercontent.com` source (line-navigable, exact) — the blob page is a CSP-locked JS SPA and code wants source, not a rendered viewer. This is the ONLY host rewrite; Wikipedia was measured through the extractor and deliberately gets none (desktop already extracts the full clean article; rewrites regressed it — schemes-http#4).
|
|
77
77
|
- **Config:** `.env.defaults` at the package root is the authoritative list (family-namespaced `PLURNK_SCHEMES_HTTP_*`), shipped in the tarball; the daemon assembles it into the boot floor set-if-unset (service SPEC §operator-config-env-defaults, schemes#31). Required render-path numerics — `FETCH_TIMEOUT`, `SALVAGE_MIN_BODY_CHARS`, `IDLE_TIMEOUT` — fail hard when unset (no in-code defaults). `MOBILE` is floor-defaulted to `1` and a required read (unset crashes). Absence-is-a-mode knobs: `PLAYWRIGHT_WS`, `NO_SANDBOX`, `CHROMIUM_HEAP_MB`.
|
|
78
78
|
- **Freshness (READ):** {§revalidation} one predicate (`#storedCopyServable`), two phases. Pre-fetch: a stored copy whose materialization stamp (`x-plurnk-fetched-at`, HEADER channel) is inside `PLURNK_SCHEMES_HTTP_TTL_MS` serves with zero round-trips — identical for model READs and lane-1 prefetch (#405); `0` disables the window. The stamp resets only when the origin vouches (fetch or 304), never on a cache serve. Past the window a repeat READ recovers the prior fetch's validators from its own stored entry (`ETag`→`If-None-Match`, `Last-Modified`→`If-Modified-Since`) and revalidates. A `304` re-serves the stored body and **skips the render** — a first-class READ (the model sees an ordinary streaming result, never a cache status; `revalidated 304` rides the close summary). The TTL is the #333 milestone landed at that same one-predicate boundary (blessed by service#341; delivered per #405). `SEND[410]` drops the stored copy, forcing the next READ to full-fetch.
|
|
79
79
|
- **Cancel:** the composed `AbortSignal` / SEND[499] handle aborts the render by closing the page (in-flight `goto` rejects promptly).
|
|
80
|
+
|
|
81
|
+
- **SSE (READ):** {§sse} a GET whose response is `text/event-stream` is parsed, not streamed raw: events split on a blank line, and each event's `data` field(s) — joined by `\n`, the `data:`/comment framing stripped, `\r\n` normalized — dispatch as one `notifyChunk("body", …, "text/plain")`. The model reads event payloads, not the wire. Comment lines (`:`) and non-`data` fields (`event`/`id`/`retry`) drop day-one; reconnection (`Last-Event-ID`) is a follow-up (#468). A long-lived GET — events land across turns until the origin closes; the close summary counts events.
|
|
82
|
+
|
|
83
|
+
## §7 Prefetch primitive {§prefetch}
|
|
84
|
+
|
|
85
|
+
`WebFetcher` is the guarded fetch/render seam core's entry-materialization calls (#454):
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
new WebFetcher().fetch(url: string, opts?: { signal?: AbortSignal }): Promise<{ body: string; mimetype: string } | null>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- **`{ body, mimetype }`** — the rendered (HTML → playwright/salvage) or raw (textual) body of a live, public, textual URL.
|
|
92
|
+
- **`null`** — dead: SSRF-refused, unreachable, non-2xx, non-textual (binary pruned), or empty. Dead-ness is a **value, not a throw** — the liveness verdict core prunes on.
|
|
93
|
+
- **SSRF guard** (`Guard`): http(s) only, no localhost, every resolved address public (RFC-reserved v4/v6 ranges blocked), with **manual per-hop redirect re-guarding**; the chromium render is guarded too via request interception. Hops capped by `PLURNK_SCHEMES_HTTP_REDIRECTS`. Residual DNS-rebinding sliver (runtime re-resolves after the check) accepted day-one.
|
|
94
|
+
- **Textual set**: `text/*`, `application/{json,xml,xhtml+xml}`, `+json`/`+xml` suffixes.
|
|
95
|
+
|
|
96
|
+
## §8 WebSocket {§ws}
|
|
97
|
+
|
|
98
|
+
`Ws` is this package's **second first-class scheme** (#468, #473): registered `wss` via `package.json` `plurnk.schemes` (`{ name: "wss", export: "Ws" }`), with the `ws` prefix riding it in core's `schemeNameOf` exactly as `https` rides `http`. WebSocket is a distinct protocol — bidirectional, stateful, full-duplex, its own URI scheme — not an http content-type (that's SSE, §sse), so it has its own manifest (🔌, `messages` channel, `docs/wss.md`) and its own directory entry the model discovers natively. Op → socket lifecycle:
|
|
99
|
+
|
|
100
|
+
- **`READ(wss://…)`** — open the socket, guard the target through `Guard.isPublicUrl` (extended to `ws:`/`wss:`), seed + subscribe (create-then-subscribe, http#3), stream each inbound frame into the `messages` channel (`notifyChunk`, text/plain). Returns `102`; the op **holds until the socket closes** (mirrors the streaming lifecycle — the worker wakes on close, summary counts messages).
|
|
101
|
+
- **`SEND[200](wss://…):msg:`** — push `msg` onto the open socket. No open socket → `409` (`kind: no_open_socket`) — READ opens the connection SEND rides.
|
|
102
|
+
- **`SEND[499](wss://…)`** — cancel; engine routes teardown to the READ's handle (which closes the socket), scheme-level `200` no-op.
|
|
103
|
+
- **`KILL(wss://…)`** — close the open socket (`404` if none open).
|
|
104
|
+
|
|
105
|
+
**Stateless-contract exception:** every other scheme is stateless per schemes SPEC §forbidden ("no state past a handler return"). A live socket IS per-workspace state, so `Ws` holds open sockets in an **in-instance registry** across op invocations — keyed `workspace:pathname`, entries present only while the socket is open (every terminal path — close/error/KILL/cancel — removes). This is the ONE sanctioned exception, because that persistence is the whole point of a WebSocket. Day-one limits: text frames only, no reconnection, default handshake identity (custom headers pending) — all #468 follow-ups.
|
package/dist/Browser.d.ts
CHANGED
|
@@ -3,7 +3,15 @@ interface PwResponse {
|
|
|
3
3
|
statusText(): string;
|
|
4
4
|
headers(): Record<string, string>;
|
|
5
5
|
}
|
|
6
|
+
interface PwRoute {
|
|
7
|
+
request(): {
|
|
8
|
+
url(): string;
|
|
9
|
+
};
|
|
10
|
+
continue(): Promise<void>;
|
|
11
|
+
abort(): Promise<void>;
|
|
12
|
+
}
|
|
6
13
|
interface PwPage {
|
|
14
|
+
route(pattern: string, handler: (route: PwRoute) => Promise<void>): Promise<void>;
|
|
7
15
|
goto(url: string, opts: {
|
|
8
16
|
waitUntil: "networkidle";
|
|
9
17
|
timeout: number;
|
|
@@ -51,13 +59,14 @@ export declare const requireNumEnv: (key: string) => number;
|
|
|
51
59
|
export default class Browser {
|
|
52
60
|
#private;
|
|
53
61
|
constructor(factory?: ChromiumFactory);
|
|
54
|
-
render(url: string, {
|
|
55
|
-
|
|
62
|
+
render(url: string, { workerId, signal, headers, guard, timeout }: {
|
|
63
|
+
workerId: number;
|
|
56
64
|
signal?: AbortSignal;
|
|
57
65
|
headers?: ReadonlyArray<readonly [string, string]>;
|
|
66
|
+
guard?: (url: string) => Promise<boolean>;
|
|
58
67
|
timeout?: number;
|
|
59
68
|
}): Promise<RenderResult>;
|
|
60
|
-
closeContext(
|
|
69
|
+
closeContext(workerId: number): void;
|
|
61
70
|
close(): Promise<void>;
|
|
62
71
|
}
|
|
63
72
|
export {};
|
package/dist/Browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"AAmBA,UAAU,UAAU;IAChB,MAAM,IAAI,MAAM,CAAC;IACjB,UAAU,IAAI,MAAM,CAAC;IACrB,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AACD,UAAU,MAAM;IACZ,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,SAAS,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnG,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AACD,UAAU,SAAS;IACf,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,UAAU,gBAAgB;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACrB;AACD,UAAU,SAAS;IACf,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3D,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAChD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AACD,MAAM,WAAW,cAAc;IAC3B,MAAM,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACrF,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACnD;AACD,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;AAO5D,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAYD,eAAO,MAAM,UAAU,0HAA0H,CAAC;AAuBlJ,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,MAM3C,CAAC;AAOF,MAAM,CAAC,OAAO,OAAO,OAAO;;IAWxB,YAAY,OAAO,GAAE,eAAgC,EAEpD;IAKK,MAAM,CACR,GAAG,EAAE,MAAM,EACX,EAAE,
|
|
1
|
+
{"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"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"}
|
package/dist/Browser.js
CHANGED
|
@@ -61,8 +61,8 @@ export default class Browser {
|
|
|
61
61
|
#factory;
|
|
62
62
|
#browser = null;
|
|
63
63
|
#launching = null;
|
|
64
|
-
// One BrowserContext per
|
|
65
|
-
// that opened it, no cross-
|
|
64
|
+
// One BrowserContext per worker — cookies / cache / storage scoped to the worker
|
|
65
|
+
// that opened it, no cross-worker bleed. Closed by closeContext() on run end
|
|
66
66
|
// or abort. The browser process stays warm across all of them.
|
|
67
67
|
#contexts = new Map();
|
|
68
68
|
#idleTimer = null;
|
|
@@ -70,12 +70,19 @@ export default class Browser {
|
|
|
70
70
|
constructor(factory = defaultFactory) {
|
|
71
71
|
this.#factory = factory;
|
|
72
72
|
}
|
|
73
|
-
// Render a URL to its final serialized DOM. Opens a page in the
|
|
73
|
+
// Render a URL to its final serialized DOM. Opens a page in the worker's
|
|
74
74
|
// context, navigates with the settle+salvage strategy, serializes, closes
|
|
75
75
|
// the page. Throws on navigation failure (the caller maps it to a status).
|
|
76
|
-
async render(url, {
|
|
77
|
-
const context = await this.#getContext(
|
|
76
|
+
async render(url, { workerId, signal, headers, guard, timeout = requireNumEnv("PLURNK_SCHEMES_HTTP_FETCH_TIMEOUT") }) {
|
|
77
|
+
const context = await this.#getContext(workerId);
|
|
78
78
|
const page = await context.newPage();
|
|
79
|
+
// SSRF interception (WebFetcher, #454): re-guard every navigation AND
|
|
80
|
+
// subresource — a rendered public page must not reach private space.
|
|
81
|
+
// Aborted requests surface as a nav/subresource failure, which the
|
|
82
|
+
// caller reads as dead. Only wired when a guard is supplied (the general
|
|
83
|
+
// READ render path passes none — unchanged).
|
|
84
|
+
if (guard)
|
|
85
|
+
await page.route("**", async (r) => { (await guard(r.request().url())) ? await r.continue() : await r.abort(); });
|
|
79
86
|
// Request headers (auth/accept) apply to the navigation too, so an authed
|
|
80
87
|
// HTML page renders authenticated. Ordered pairs collapse to a record here
|
|
81
88
|
// — Playwright's per-page header API is single-valued (dup names not a
|
|
@@ -130,8 +137,8 @@ export default class Browser {
|
|
|
130
137
|
}
|
|
131
138
|
// Get-or-launch the warm chromium. Connects to a remote CDP endpoint via
|
|
132
139
|
// PLURNK_SCHEMES_HTTP_PLAYWRIGHT_WS if set (shared / Lightpanda /
|
|
133
|
-
// browserless), else launches locally. Single browser across all
|
|
134
|
-
// per-
|
|
140
|
+
// browserless), else launches locally. Single browser across all workers;
|
|
141
|
+
// per-worker isolation is at the context layer. Relaunches if chromium dies
|
|
135
142
|
// (OOM/segfault/WS teardown) leaves the handle stale.
|
|
136
143
|
async #getBrowser() {
|
|
137
144
|
this.#touchIdle();
|
|
@@ -161,26 +168,26 @@ export default class Browser {
|
|
|
161
168
|
this.#browser = browser;
|
|
162
169
|
return browser;
|
|
163
170
|
}
|
|
164
|
-
// Get-or-create the
|
|
171
|
+
// Get-or-create the worker's BrowserContext. Mobile-emulated by default (a
|
|
165
172
|
// lighter responsive layout is the better generation hint); desktop when
|
|
166
173
|
// PLURNK_SCHEMES_HTTP_MOBILE=0.
|
|
167
|
-
async #getContext(
|
|
174
|
+
async #getContext(workerId) {
|
|
168
175
|
this.#touchIdle();
|
|
169
|
-
const existing = this.#contexts.get(
|
|
176
|
+
const existing = this.#contexts.get(workerId);
|
|
170
177
|
if (existing)
|
|
171
178
|
return existing;
|
|
172
179
|
const browser = await this.#getBrowser();
|
|
173
180
|
const context = await browser.newContext(mobileEmulation());
|
|
174
|
-
this.#contexts.set(
|
|
181
|
+
this.#contexts.set(workerId, context);
|
|
175
182
|
return context;
|
|
176
183
|
}
|
|
177
|
-
// Drop the
|
|
184
|
+
// Drop the worker's context (run end or abort). Closing it cascades to any
|
|
178
185
|
// in-flight page in that context. Fire-and-forget.
|
|
179
|
-
closeContext(
|
|
180
|
-
const context = this.#contexts.get(
|
|
186
|
+
closeContext(workerId) {
|
|
187
|
+
const context = this.#contexts.get(workerId);
|
|
181
188
|
if (!context)
|
|
182
189
|
return;
|
|
183
|
-
this.#contexts.delete(
|
|
190
|
+
this.#contexts.delete(workerId);
|
|
184
191
|
context.close().catch(() => { });
|
|
185
192
|
}
|
|
186
193
|
#touchIdle() {
|
|
@@ -189,7 +196,7 @@ export default class Browser {
|
|
|
189
196
|
this.#idleTimer = setTimeout(() => { this.close().catch(() => { }); }, requireNumEnv("PLURNK_SCHEMES_HTTP_IDLE_TIMEOUT"));
|
|
190
197
|
this.#idleTimer.unref?.();
|
|
191
198
|
}
|
|
192
|
-
// Tear everything down: per-
|
|
199
|
+
// Tear everything down: per-worker contexts then the browser. In CDP mode
|
|
193
200
|
// close() disconnects the local handle without shutting the remote down.
|
|
194
201
|
async close() {
|
|
195
202
|
if (this.#idleTimer) {
|
package/dist/Browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Browser.js","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kFAAkF;AAClF,4EAA4E;AAC5E,8EAA8E;AAC9E,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,2CAA2C;AAC3C,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,0EAA0E;AAC1E,sDAAsD;
|
|
1
|
+
{"version":3,"file":"Browser.js","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"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"}
|
package/dist/Guard.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class GuardBlockedError extends Error {
|
|
2
|
+
readonly url: string;
|
|
3
|
+
constructor(url: string);
|
|
4
|
+
}
|
|
5
|
+
export default class Guard {
|
|
6
|
+
static isPublicAddress(ip: string): boolean;
|
|
7
|
+
static isPublicUrl(raw: string): Promise<boolean>;
|
|
8
|
+
static fetch(raw: string, init: {
|
|
9
|
+
method: string;
|
|
10
|
+
body: string | undefined;
|
|
11
|
+
headers: Array<[string, string]>;
|
|
12
|
+
}, signal: AbortSignal): Promise<Response>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=Guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Guard.d.ts","sourceRoot":"","sources":["../src/Guard.ts"],"names":[],"mappings":"AAeA,qBAAa,iBAAkB,SAAQ,KAAK;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,YAAY,GAAG,EAAE,MAAM,EAItB;CACJ;AAED,MAAM,CAAC,OAAO,OAAO,KAAK;IAItB,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiB1C;IAMD,OAAa,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAatD;IAOD,OAAa,KAAK,CACd,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,EACpF,MAAM,EAAE,WAAW,GACpB,OAAO,CAAC,QAAQ,CAAC,CAkBnB;CACJ"}
|
package/dist/Guard.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// SSRF guard for the fetch path (#456; ported from execs-search Pages.ts, which
|
|
2
|
+
// deletes its copy as prefetch delegates here — execs #387). Every request —
|
|
3
|
+
// the initial target AND every redirect hop — must resolve to a PUBLIC address:
|
|
4
|
+
// a public URL redirecting into private space is the classic SSRF, so redirects
|
|
5
|
+
// are followed MANUALLY and re-guarded per hop. The residual DNS-rebinding
|
|
6
|
+
// sliver (the runtime re-resolves after our check) is accepted day-one, same as
|
|
7
|
+
// the reference. Byte path only day-one; the chromium render navigation is a
|
|
8
|
+
// separate surface tracked on #456.
|
|
9
|
+
import dns from "node:dns/promises";
|
|
10
|
+
import net from "node:net";
|
|
11
|
+
import { requireNumEnv } from "./Browser.js";
|
|
12
|
+
// A target (or a redirect hop) that resolved to a non-public address. Http maps
|
|
13
|
+
// it to a 403 dead-signal, distinct from a network 502.
|
|
14
|
+
export class GuardBlockedError extends Error {
|
|
15
|
+
url;
|
|
16
|
+
constructor(url) {
|
|
17
|
+
super(`SSRF guard: ${url} is not a public http(s) target`);
|
|
18
|
+
this.name = "GuardBlockedError";
|
|
19
|
+
this.url = url;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export default class Guard {
|
|
23
|
+
// RFC-reserved ranges (protocol constants, never tunables): loopback,
|
|
24
|
+
// RFC1918, link-local/metadata (169.254), CGNAT (100.64/10), unspecified,
|
|
25
|
+
// 0.0.0.0/8; v6 ULA + link-local + v4-mapped re-checked as v4.
|
|
26
|
+
static isPublicAddress(ip) {
|
|
27
|
+
if (net.isIP(ip) === 4) {
|
|
28
|
+
const [a, b] = ip.split(".").map(Number);
|
|
29
|
+
if (a === 0 || a === 10 || a === 127)
|
|
30
|
+
return false;
|
|
31
|
+
if (a === 169 && b === 254)
|
|
32
|
+
return false;
|
|
33
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
34
|
+
return false;
|
|
35
|
+
if (a === 192 && b === 168)
|
|
36
|
+
return false;
|
|
37
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
38
|
+
return false;
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
const v6 = ip.toLowerCase();
|
|
42
|
+
if (v6 === "::" || v6 === "::1")
|
|
43
|
+
return false;
|
|
44
|
+
if (v6.startsWith("fc") || v6.startsWith("fd"))
|
|
45
|
+
return false;
|
|
46
|
+
if (/^fe[89ab]/.test(v6))
|
|
47
|
+
return false;
|
|
48
|
+
const mapped = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/.exec(v6);
|
|
49
|
+
if (mapped !== null)
|
|
50
|
+
return Guard.isPublicAddress(mapped[1]);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
// http(s)/ws(s) only, no localhost, and EVERY resolved address public. An IP
|
|
54
|
+
// literal skips DNS; a hostname resolves and every A/AAAA must be public.
|
|
55
|
+
// ws:/wss: ride the same range check — a WebSocket into private space is the
|
|
56
|
+
// same SSRF as a fetch (the Ws scheme guards its target through here).
|
|
57
|
+
static async isPublicUrl(raw) {
|
|
58
|
+
let url;
|
|
59
|
+
try {
|
|
60
|
+
url = new URL(raw);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (!["http:", "https:", "ws:", "wss:"].includes(url.protocol))
|
|
66
|
+
return false;
|
|
67
|
+
const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
68
|
+
if (host === "localhost" || host.endsWith(".localhost"))
|
|
69
|
+
return false;
|
|
70
|
+
if (net.isIP(host))
|
|
71
|
+
return Guard.isPublicAddress(host);
|
|
72
|
+
try {
|
|
73
|
+
const addrs = await dns.lookup(host, { all: true });
|
|
74
|
+
return addrs.length > 0 && addrs.every(({ address }) => Guard.isPublicAddress(address));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false; // unresolvable is dead anyway
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Guarded fetch: re-guard every hop, follow up to PLURNK_SCHEMES_HTTP_REDIRECTS
|
|
81
|
+
// manually (floor-set knob — unset crashes). Method/body downgrade follows the
|
|
82
|
+
// fetch spec (301/302 on a non-GET/HEAD and any 303 → GET, body dropped;
|
|
83
|
+
// 307/308 preserve). Throws GuardBlockedError on a private hop; hands back the
|
|
84
|
+
// final response (incl. a terminal 3xx when hops run out) otherwise.
|
|
85
|
+
static async fetch(raw, init, signal) {
|
|
86
|
+
let target = raw;
|
|
87
|
+
let method = init.method;
|
|
88
|
+
let body = init.body;
|
|
89
|
+
let hops = requireNumEnv("PLURNK_SCHEMES_HTTP_REDIRECTS");
|
|
90
|
+
while (true) {
|
|
91
|
+
if (!(await Guard.isPublicUrl(target)))
|
|
92
|
+
throw new GuardBlockedError(target);
|
|
93
|
+
const response = await fetch(target, { method, body, headers: init.headers, signal, redirect: "manual" });
|
|
94
|
+
if (response.status < 300 || response.status >= 400)
|
|
95
|
+
return response;
|
|
96
|
+
const location = response.headers.get("location");
|
|
97
|
+
if (location === null || hops <= 0)
|
|
98
|
+
return response;
|
|
99
|
+
hops -= 1;
|
|
100
|
+
target = new URL(location, target).href;
|
|
101
|
+
if (response.status === 303 || ((response.status === 301 || response.status === 302) && method !== "GET" && method !== "HEAD")) {
|
|
102
|
+
method = "GET";
|
|
103
|
+
body = undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=Guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Guard.js","sourceRoot":"","sources":["../src/Guard.ts"],"names":[],"mappings":"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"}
|
package/dist/Http.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { SchemeCtx, PassthroughResult, SchemeManifest, SchemeHandler, ReadS
|
|
|
2
2
|
import { type RenderResult } from "./Browser.ts";
|
|
3
3
|
interface Renderer {
|
|
4
4
|
render(url: string, opts: {
|
|
5
|
-
|
|
5
|
+
workerId: number;
|
|
6
6
|
signal?: AbortSignal;
|
|
7
7
|
headers?: ReadonlyArray<readonly [string, string]>;
|
|
8
8
|
}): Promise<RenderResult>;
|
package/dist/Http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../src/Http.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACR,SAAS,EAET,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EAGhB,MAAM,wBAAwB,CAAC;AAGhC,OAAgB,EAA6B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAkBrF,UAAU,QAAQ;IACd,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,
|
|
1
|
+
{"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../src/Http.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACR,SAAS,EAET,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EAGhB,MAAM,wBAAwB,CAAC;AAGhC,OAAgB,EAA6B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAkBrF,UAAU,QAAQ;IACd,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACpJ;AAED,MAAM,CAAC,OAAO,OAAO,IAAK,YAAW,aAAa;;IAC9C,MAAM,CAAC,QAAQ,EAAE,cAAc,CAoB7B;IAKF,YAAY,OAAO,GAAE,QAAwB,EAE5C;IAKK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAK/E;IAIK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAQ/E;IAIK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAK/E;IAQK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqB/E;CAwRJ"}
|
package/dist/Http.js
CHANGED
|
@@ -51,7 +51,7 @@ class Http {
|
|
|
51
51
|
channels: { [BODY]: "application/octet-stream", [HEADER]: "text/plain" },
|
|
52
52
|
defaultChannel: BODY,
|
|
53
53
|
category: "data",
|
|
54
|
-
scope: "
|
|
54
|
+
scope: "workspace",
|
|
55
55
|
writableBy: ["model", "client"],
|
|
56
56
|
volatile: true, // remote content can change between fetches
|
|
57
57
|
modelVisible: true,
|
|
@@ -70,7 +70,7 @@ class Http {
|
|
|
70
70
|
}
|
|
71
71
|
// READ → fetch; an HTML page is rendered, everything else streams raw.
|
|
72
72
|
// Returns 102 Processing; the subscription drives the channel content the
|
|
73
|
-
// model sees next turn.
|
|
73
|
+
// model sees next turn. (ws/wss dispatch to the Ws scheme directly — #473.)
|
|
74
74
|
async read(statement, ctx) {
|
|
75
75
|
if (statement.target === null || statement.target.kind !== "url") {
|
|
76
76
|
return _a.#bad(400, "http", "bad_target", "READ requires an http(s):// URL target");
|
|
@@ -176,7 +176,7 @@ class Http {
|
|
|
176
176
|
// whose channels are the manifest's (body: octet-stream placeholder,
|
|
177
177
|
// header: text/plain) — the same channels notifyChunk then populates.
|
|
178
178
|
await ctx.entries.write(pathname, _a.#seedEntry());
|
|
179
|
-
// open() returns the
|
|
179
|
+
// open() returns the worker+teardown-composed signal — fires on loop.cancel
|
|
180
180
|
// OR our local teardown. Wire it so either path aborts the fetch/render.
|
|
181
181
|
const composed = await ctx.subscriptions.open(pathname, handle);
|
|
182
182
|
const onAbort = () => local.abort();
|
|
@@ -215,12 +215,21 @@ class Http {
|
|
|
215
215
|
&& /^(?:text\/html|application\/xhtml\+xml)\b/i.test(contentType);
|
|
216
216
|
if (isHtml) {
|
|
217
217
|
await response.body?.cancel();
|
|
218
|
-
const result = await this.#browser.render(url, {
|
|
218
|
+
const result = await this.#browser.render(url, { workerId: ctx.workerId, signal: local.signal, headers });
|
|
219
219
|
await _a.#writeHeader(ctx, result.status, result.statusText, result.headers);
|
|
220
220
|
await ctx.subscriptions.notifyChunk(BODY, result.html, "text/html");
|
|
221
221
|
await ctx.subscriptions.close("done", `rendered HTTP ${result.status}; ${result.html.length} chars`);
|
|
222
222
|
return { shape: "passthrough", status: 102 };
|
|
223
223
|
}
|
|
224
|
+
// SSE: an event stream is parsed into its `data` payloads (SPEC §sse),
|
|
225
|
+
// one notifyChunk per event with the `data:`/comment framing stripped,
|
|
226
|
+
// so the model reads event content and not the transport. A long-lived
|
|
227
|
+
// GET; events land in the body channel as they arrive across turns,
|
|
228
|
+
// until the origin closes. Only GET — a POST reply is never an SSE READ.
|
|
229
|
+
if (method === "GET" && /^text\/event-stream\b/i.test(contentType)) {
|
|
230
|
+
await _a.#writeHeader(ctx, response.status, response.statusText, [...response.headers]);
|
|
231
|
+
return await _a.#streamEvents(ctx, response);
|
|
232
|
+
}
|
|
224
233
|
// Byte path: stream the body labelled with its real content type.
|
|
225
234
|
await _a.#writeHeader(ctx, response.status, response.statusText, [...response.headers]);
|
|
226
235
|
const bodyMime = contentType.split(";")[0].trim() || "application/octet-stream";
|
|
@@ -268,6 +277,46 @@ class Http {
|
|
|
268
277
|
lines.push(`${FETCHED_AT}: ${new Date().toISOString()}`);
|
|
269
278
|
await ctx.subscriptions.notifyChunk(HEADER, lines.join("\n"), "text/plain");
|
|
270
279
|
}
|
|
280
|
+
// Drain an SSE body, dispatching one BODY chunk per event — the event's
|
|
281
|
+
// `data` field(s) joined by \n, framing stripped (SPEC §sse). Events split on
|
|
282
|
+
// a blank line; CRs normalized so \r\n frames parse. Comment lines (`:`) and
|
|
283
|
+
// non-`data` fields (event/id/retry) drop day-one — payloads, not the wire.
|
|
284
|
+
// No reconnection day-one (Last-Event-ID is a schemes-http follow-up).
|
|
285
|
+
static async #streamEvents(ctx, response) {
|
|
286
|
+
if (response.body === null) {
|
|
287
|
+
await ctx.subscriptions.close("done", "SSE stream; empty body");
|
|
288
|
+
return { shape: "passthrough", status: 102 };
|
|
289
|
+
}
|
|
290
|
+
const decoder = new TextDecoder();
|
|
291
|
+
let buffer = "";
|
|
292
|
+
let events = 0;
|
|
293
|
+
for await (const chunk of response.body) {
|
|
294
|
+
buffer += decoder.decode(chunk, { stream: true }).replace(/\r\n?/g, "\n");
|
|
295
|
+
let sep;
|
|
296
|
+
while ((sep = buffer.indexOf("\n\n")) !== -1) {
|
|
297
|
+
const data = _a.#eventData(buffer.slice(0, sep));
|
|
298
|
+
buffer = buffer.slice(sep + 2);
|
|
299
|
+
if (data === null)
|
|
300
|
+
continue;
|
|
301
|
+
events += 1;
|
|
302
|
+
await ctx.subscriptions.notifyChunk(BODY, `${data}\n`, "text/plain");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
await ctx.subscriptions.close("done", `SSE stream; ${events} events`);
|
|
306
|
+
return { shape: "passthrough", status: 102 };
|
|
307
|
+
}
|
|
308
|
+
// One SSE frame → its `data` payload (multiple `data:` lines joined by \n,
|
|
309
|
+
// one optional leading space after the colon stripped), or null when the
|
|
310
|
+
// frame carried no `data` field at all.
|
|
311
|
+
static #eventData(frame) {
|
|
312
|
+
const data = [];
|
|
313
|
+
for (const line of frame.split("\n")) {
|
|
314
|
+
if (!line.startsWith("data:"))
|
|
315
|
+
continue;
|
|
316
|
+
data.push(line.slice(5).replace(/^ /, ""));
|
|
317
|
+
}
|
|
318
|
+
return data.length > 0 ? data.join("\n") : null;
|
|
319
|
+
}
|
|
271
320
|
// Reconstruct the absolute URL from the parsed UrlPath. `raw` is the
|
|
272
321
|
// grammar's verbatim URL — authoritative; the decomposed fields are a
|
|
273
322
|
// convenience. Use raw so query strings / auth / port survive exactly.
|
package/dist/Http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Http.js","sourceRoot":"","sources":["../src/Http.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Http.js","sourceRoot":"","sources":["../src/Http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type RenderResult } from "./Browser.ts";
|
|
2
|
+
interface Renderer {
|
|
3
|
+
render(url: string, opts: {
|
|
4
|
+
workerId: number;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
headers?: ReadonlyArray<readonly [string, string]>;
|
|
7
|
+
guard?: (url: string) => Promise<boolean>;
|
|
8
|
+
}): Promise<RenderResult>;
|
|
9
|
+
}
|
|
10
|
+
export default class WebFetcher {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(browser?: Renderer);
|
|
13
|
+
fetch(url: string, opts?: {
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
body: string;
|
|
17
|
+
mimetype: string;
|
|
18
|
+
} | null>;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=WebFetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetcher.d.ts","sourceRoot":"","sources":["../src/WebFetcher.ts"],"names":[],"mappings":"AAMA,OAAgB,EAA6B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAerF,UAAU,QAAQ;IACd,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC7C,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7B;AAED,MAAM,CAAC,OAAO,OAAO,UAAU;;IAI3B,YAAY,OAAO,GAAE,QAAwB,EAE5C;IAEK,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAkC5G;CACJ"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// The guarded fetch/render prefetch primitive core's entrySink calls (#454).
|
|
2
|
+
// ONE seam (SPEC §prefetch): `fetch(url) → { body, mimetype } | null`. Dead-ness is a VALUE,
|
|
3
|
+
// never a throw — null covers SSRF-refused, unreachable, non-2xx, non-textual,
|
|
4
|
+
// and empty. Everything behind it (plain fetch vs playwright/salvage, redirect
|
|
5
|
+
// hops, per-page timeout, the SSRF guard) is ours.
|
|
6
|
+
import Browser, { BROWSER_UA, requireNumEnv } from "./Browser.js";
|
|
7
|
+
import Guard from "./Guard.js";
|
|
8
|
+
// Day-one textual set (owner ruling, #454): text/* plus the +json/+xml family.
|
|
9
|
+
// Non-textual bodies (pdf, images) prune to null — they don't survive the
|
|
10
|
+
// string entry() contract core prefetches into.
|
|
11
|
+
const isTextual = (mimetype) => mimetype.startsWith("text/")
|
|
12
|
+
|| ["application/json", "application/xml", "application/xhtml+xml"].includes(mimetype)
|
|
13
|
+
|| mimetype.endsWith("+json") || mimetype.endsWith("+xml");
|
|
14
|
+
const isHtml = (mimetype) => mimetype === "text/html" || mimetype === "application/xhtml+xml";
|
|
15
|
+
export default class WebFetcher {
|
|
16
|
+
// One warm-Chromium pool shared across prefetches (render context keyed 0 —
|
|
17
|
+
// prefetch is public-page acquisition, no per-worker cookie isolation to keep).
|
|
18
|
+
#browser;
|
|
19
|
+
constructor(browser = new Browser()) {
|
|
20
|
+
this.#browser = browser;
|
|
21
|
+
}
|
|
22
|
+
async fetch(url, opts) {
|
|
23
|
+
const timeout = AbortSignal.timeout(requireNumEnv("PLURNK_SCHEMES_HTTP_FETCH_TIMEOUT"));
|
|
24
|
+
const signal = opts?.signal ? AbortSignal.any([opts.signal, timeout]) : timeout;
|
|
25
|
+
let response;
|
|
26
|
+
try {
|
|
27
|
+
response = await Guard.fetch(url, { method: "GET", body: undefined, headers: [["User-Agent", BROWSER_UA]] }, signal);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null; // SSRF-refused or unreachable — both dead
|
|
31
|
+
}
|
|
32
|
+
const mimetype = (response.headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
await response.body?.cancel();
|
|
35
|
+
return null;
|
|
36
|
+
} // non-2xx dead
|
|
37
|
+
// HTML → render (playwright/salvage); the guard re-checks every navigation
|
|
38
|
+
// and subresource, so a public page redirecting into private space is
|
|
39
|
+
// refused at the browser too, not just the probe fetch.
|
|
40
|
+
if (isHtml(mimetype)) {
|
|
41
|
+
await response.body?.cancel();
|
|
42
|
+
try {
|
|
43
|
+
const rendered = await this.#browser.render(url, {
|
|
44
|
+
workerId: 0,
|
|
45
|
+
signal,
|
|
46
|
+
headers: [["User-Agent", BROWSER_UA]],
|
|
47
|
+
guard: Guard.isPublicUrl,
|
|
48
|
+
});
|
|
49
|
+
return rendered.html.length > 0 ? { body: rendered.html, mimetype: "text/html" } : null;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null; // render failure (nav error, timeout, guard-aborted) is dead
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!isTextual(mimetype)) {
|
|
56
|
+
await response.body?.cancel();
|
|
57
|
+
return null;
|
|
58
|
+
} // binary pruned
|
|
59
|
+
const body = await response.text();
|
|
60
|
+
return body.length > 0 ? { body, mimetype } : null; // empty is dead
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=WebFetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetcher.js","sourceRoot":"","sources":["../src/WebFetcher.ts"],"names":[],"mappings":"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"}
|
package/dist/Ws.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SchemeCtx, PassthroughResult, SchemeManifest, SchemeHandler, ReadStatement, SendStatement, KillStatement } from "@plurnk/plurnk-schemes";
|
|
2
|
+
interface SocketEvent {
|
|
3
|
+
readonly data?: unknown;
|
|
4
|
+
readonly code?: number;
|
|
5
|
+
readonly reason?: string;
|
|
6
|
+
readonly message?: string;
|
|
7
|
+
}
|
|
8
|
+
interface Socket {
|
|
9
|
+
addEventListener(type: "open" | "message" | "close" | "error", listener: (event: SocketEvent) => void): void;
|
|
10
|
+
send(data: string): void;
|
|
11
|
+
close(code?: number, reason?: string): void;
|
|
12
|
+
}
|
|
13
|
+
type SocketFactory = (url: string) => Socket;
|
|
14
|
+
export default class Ws implements SchemeHandler {
|
|
15
|
+
#private;
|
|
16
|
+
static manifest: SchemeManifest;
|
|
17
|
+
constructor(connect?: SocketFactory);
|
|
18
|
+
read(statement: ReadStatement, ctx: SchemeCtx): Promise<PassthroughResult>;
|
|
19
|
+
send(statement: SendStatement, ctx: SchemeCtx): Promise<PassthroughResult>;
|
|
20
|
+
kill(statement: KillStatement, ctx: SchemeCtx): Promise<PassthroughResult>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=Ws.d.ts.map
|
package/dist/Ws.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ws.d.ts","sourceRoot":"","sources":["../src/Ws.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACR,SAAS,EAET,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EAEhB,MAAM,wBAAwB,CAAC;AAahC,UAAU,WAAW;IACjB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC7B;AACD,UAAU,MAAM;IACZ,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7G,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AACD,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAQ7C,MAAM,CAAC,OAAO,OAAO,EAAG,YAAW,aAAa;;IAC5C,MAAM,CAAC,QAAQ,EAAE,cAAc,CAe7B;IAOF,YAAY,OAAO,GAAE,aAA6B,EAEjD;IAKK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmD/E;IAIK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAe/E;IAIK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU/E;CAkBJ"}
|
package/dist/Ws.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// ws(s):// scheme handler — this package's second first-class scheme (#468,
|
|
2
|
+
// #473): registered `wss` via package.json plurnk.schemes ({ export: "Ws" });
|
|
3
|
+
// the `ws` prefix rides it (core's schemeNameOf, mirroring https → http).
|
|
4
|
+
// WebSocket IS a distinct protocol — bidirectional, stateful, full-duplex — not
|
|
5
|
+
// an http content-type (that's SSE, Http.#streamEvents), so it's its own
|
|
6
|
+
// scheme, not a branch in the fetch path.
|
|
7
|
+
//
|
|
8
|
+
// Op → socket lifecycle (SPEC §ws):
|
|
9
|
+
// READ(wss://host/path) — open the socket; inbound frames stream into the
|
|
10
|
+
// `messages` channel; the op holds until close.
|
|
11
|
+
// SEND[200](wss://...):msg: — push `msg` onto the open socket (READ it first).
|
|
12
|
+
// SEND[499](wss://...) — cancel: the engine routes to the READ's handle,
|
|
13
|
+
// which closes the socket (scheme-level no-op).
|
|
14
|
+
// KILL(wss://...) — close the open socket.
|
|
15
|
+
//
|
|
16
|
+
// Stateful exception: every other scheme is stateless per the schemes SPEC
|
|
17
|
+
// §forbidden "no state past a handler return" rule. A live socket IS per-workspace
|
|
18
|
+
// state, so this engine holds open sockets in an in-instance registry across op
|
|
19
|
+
// invocations (keyed workspace+pathname) — the ONE sanctioned exception (SPEC §ws),
|
|
20
|
+
// because that persistence is the whole point of a WebSocket. Entries live only
|
|
21
|
+
// while the socket is open; every terminal path (close/error/KILL/cancel) removes.
|
|
22
|
+
//
|
|
23
|
+
// The SSRF Guard re-checks the target before connecting (a ws into private space
|
|
24
|
+
// is the same attack as a fetch). Node ≥22 global `WebSocket` at runtime; tests
|
|
25
|
+
// inject a fake socket.
|
|
26
|
+
import { Results } from "@plurnk/plurnk-schemes";
|
|
27
|
+
import { readFile } from "node:fs/promises";
|
|
28
|
+
import Guard from "./Guard.js";
|
|
29
|
+
// The inbound-frame channel — every message the origin pushes streams here.
|
|
30
|
+
const MESSAGES = "messages";
|
|
31
|
+
const documentation = await readFile(new URL("../docs/wss.md", import.meta.url), "utf-8");
|
|
32
|
+
// Default: the Node ≥22 global WebSocket, reached through globalThis so the lib
|
|
33
|
+
// typing is not a compile dependency (tests always inject, so this path is
|
|
34
|
+
// runtime-only). Fail-hard if the runtime lacks it.
|
|
35
|
+
const connectGlobal = (url) => new globalThis.WebSocket(url);
|
|
36
|
+
export default class Ws {
|
|
37
|
+
static manifest = {
|
|
38
|
+
name: "wss",
|
|
39
|
+
channels: { [MESSAGES]: "text/plain" },
|
|
40
|
+
defaultChannel: MESSAGES,
|
|
41
|
+
category: "data",
|
|
42
|
+
scope: "workspace",
|
|
43
|
+
writableBy: ["model", "client"],
|
|
44
|
+
volatile: true,
|
|
45
|
+
modelVisible: true,
|
|
46
|
+
glyph: "🔌",
|
|
47
|
+
example: "<<READ(wss://echo.websocket.events)::READ",
|
|
48
|
+
documentation,
|
|
49
|
+
flags: {
|
|
50
|
+
requiresWeb: true,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
// The socket factory (injectable for tests) and the live-connection registry
|
|
54
|
+
// — the stateless-contract exception (SPEC §ws). One socket per
|
|
55
|
+
// workspace+pathname; SEND/KILL find the socket a prior READ opened.
|
|
56
|
+
#connect;
|
|
57
|
+
#sockets = new Map();
|
|
58
|
+
constructor(connect = connectGlobal) {
|
|
59
|
+
this.#connect = connect;
|
|
60
|
+
}
|
|
61
|
+
// READ → open the socket, stream inbound frames into `messages`, hold the op
|
|
62
|
+
// until the socket closes (mirrors the http streaming lifecycle: 102 now, the
|
|
63
|
+
// subscription drives content, the worker wakes on close).
|
|
64
|
+
async read(statement, ctx) {
|
|
65
|
+
if (statement.target === null || statement.target.kind !== "url") {
|
|
66
|
+
return Ws.#bad(400, "bad_target", "READ requires a ws(s):// URL target");
|
|
67
|
+
}
|
|
68
|
+
const url = statement.target.raw;
|
|
69
|
+
const pathname = statement.target.pathname;
|
|
70
|
+
if (!(await Guard.isPublicUrl(url))) {
|
|
71
|
+
return Ws.#bad(403, "ssrf_blocked", `${url} is not a public ws(s):// target`);
|
|
72
|
+
}
|
|
73
|
+
const key = Ws.#key(ctx.workspaceId, pathname);
|
|
74
|
+
// Create-then-subscribe (http#3): seed the messages channel, then bind.
|
|
75
|
+
await ctx.entries.write(pathname, Ws.#seedEntry());
|
|
76
|
+
const handle = { cancel: () => this.#sockets.get(key)?.close(1000, "cancelled") };
|
|
77
|
+
const composed = await ctx.subscriptions.open(pathname, handle);
|
|
78
|
+
let socket;
|
|
79
|
+
try {
|
|
80
|
+
socket = this.#connect(url);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
await ctx.subscriptions.close("error", err instanceof Error ? err.message : String(err));
|
|
84
|
+
return Ws.#bad(502, "connect_failed", err instanceof Error ? err.message : String(err));
|
|
85
|
+
}
|
|
86
|
+
this.#sockets.set(key, socket);
|
|
87
|
+
const onAbort = () => socket.close(1000, "cancelled");
|
|
88
|
+
composed.addEventListener("abort", onAbort, { once: true });
|
|
89
|
+
let messages = 0;
|
|
90
|
+
let settled = false;
|
|
91
|
+
return await new Promise((resolve) => {
|
|
92
|
+
const settle = (result, reason, outcome) => {
|
|
93
|
+
if (settled)
|
|
94
|
+
return;
|
|
95
|
+
settled = true;
|
|
96
|
+
this.#sockets.delete(key);
|
|
97
|
+
composed.removeEventListener("abort", onAbort);
|
|
98
|
+
void ctx.subscriptions.close(reason, outcome).then(() => resolve(result));
|
|
99
|
+
};
|
|
100
|
+
socket.addEventListener("message", (event) => {
|
|
101
|
+
messages += 1;
|
|
102
|
+
void ctx.subscriptions.notifyChunk(MESSAGES, String(event.data ?? ""), "text/plain");
|
|
103
|
+
});
|
|
104
|
+
socket.addEventListener("error", (event) => {
|
|
105
|
+
const reason = event.message ?? "ws error";
|
|
106
|
+
settle(Ws.#bad(502, "ws_error", reason), "error", reason);
|
|
107
|
+
});
|
|
108
|
+
socket.addEventListener("close", (event) => {
|
|
109
|
+
settle({ shape: "passthrough", status: 102 }, "done", `ws closed (${event.code ?? 0}); ${messages} messages`);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// SEND[200] → push a message onto the open socket. SEND[499] → cancel (engine
|
|
114
|
+
// routes to the READ handle; scheme no-op, mirroring http). Other codes 501.
|
|
115
|
+
async send(statement, ctx) {
|
|
116
|
+
if (statement.target === null || statement.target.kind !== "url") {
|
|
117
|
+
return Ws.#bad(400, "bad_target", "SEND requires a ws(s):// URL target");
|
|
118
|
+
}
|
|
119
|
+
const status = statement.signal;
|
|
120
|
+
if (status === 499)
|
|
121
|
+
return { shape: "passthrough", status: 200 };
|
|
122
|
+
if (status === 200) {
|
|
123
|
+
const socket = this.#sockets.get(Ws.#key(ctx.workspaceId, statement.target.pathname));
|
|
124
|
+
if (socket === undefined) {
|
|
125
|
+
return Ws.#bad(409, "no_open_socket", `no open ws for ${statement.target.pathname} — READ it first`);
|
|
126
|
+
}
|
|
127
|
+
socket.send(statement.body?.raw ?? "");
|
|
128
|
+
return { shape: "passthrough", status: 200 };
|
|
129
|
+
}
|
|
130
|
+
return Ws.#bad(501, "unsupported_send", `SEND[${status}] not supported by wss`);
|
|
131
|
+
}
|
|
132
|
+
// KILL → close the open socket. The READ's close listener deregisters it and
|
|
133
|
+
// settles the subscription, so KILL only trips the close.
|
|
134
|
+
async kill(statement, ctx) {
|
|
135
|
+
if (statement.target === null || statement.target.kind !== "url") {
|
|
136
|
+
return Ws.#bad(400, "bad_target", "KILL requires a ws(s):// URL target");
|
|
137
|
+
}
|
|
138
|
+
const socket = this.#sockets.get(Ws.#key(ctx.workspaceId, statement.target.pathname));
|
|
139
|
+
if (socket === undefined) {
|
|
140
|
+
return Ws.#bad(404, "no_open_socket", `no open ws for ${statement.target.pathname}`);
|
|
141
|
+
}
|
|
142
|
+
socket.close(1000, "killed");
|
|
143
|
+
return { shape: "passthrough", status: 200 };
|
|
144
|
+
}
|
|
145
|
+
static #key(workspaceId, pathname) {
|
|
146
|
+
return `${workspaceId}:${pathname}`;
|
|
147
|
+
}
|
|
148
|
+
// Seed entry mirroring the manifest channel (empty content + seed mimetype),
|
|
149
|
+
// so open() binds an existing entry (http#3) — same shape as Http.#seedEntry.
|
|
150
|
+
static #seedEntry() {
|
|
151
|
+
const channels = Object.fromEntries(Object.entries(Ws.manifest.channels).map(([name, mimetype]) => [name, { content: "", mimetype }]));
|
|
152
|
+
return { channels, tags: [] };
|
|
153
|
+
}
|
|
154
|
+
static #bad(status, kind, message) {
|
|
155
|
+
return { shape: "passthrough", status, error: Results.error("wss", kind, message) };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=Ws.js.map
|
package/dist/Ws.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ws.js","sourceRoot":"","sources":["../src/Ws.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { default } from "./Http.ts";
|
|
2
2
|
export { default as Http } from "./Http.ts";
|
|
3
|
+
export { default as Ws } from "./Ws.ts";
|
|
3
4
|
export { default as Browser } from "./Browser.ts";
|
|
4
5
|
export type { ChromiumEngine, ChromiumFactory, RenderResult } from "./Browser.ts";
|
|
6
|
+
export { default as WebFetcher } from "./WebFetcher.ts";
|
|
7
|
+
export { default as Guard, GuardBlockedError } from "./Guard.ts";
|
|
5
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAK5C,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAIxC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIlF,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,15 @@
|
|
|
3
3
|
// (plugin discovery scans node_modules/@plurnk/* for `plurnk.kind === "scheme"`).
|
|
4
4
|
export { default } from "./Http.js";
|
|
5
5
|
export { default as Http } from "./Http.js";
|
|
6
|
+
// The WebSocket scheme (#468/#473) — this package's second first-class scheme,
|
|
7
|
+
// registered `wss` via package.json plurnk.schemes ({ export: "Ws" }); the `ws`
|
|
8
|
+
// prefix rides it (core's schemeNameOf, mirroring https → http).
|
|
9
|
+
export { default as Ws } from "./Ws.js";
|
|
6
10
|
// Standalone render foundation — exported so a future plurnk browser-
|
|
7
11
|
// troubleshooting MCP package can sit on the same warm-Chromium pool.
|
|
8
12
|
export { default as Browser } from "./Browser.js";
|
|
13
|
+
// The guarded fetch/render prefetch seam core's entrySink calls (#454):
|
|
14
|
+
// `new WebFetcher().fetch(url) → { body, mimetype } | null`.
|
|
15
|
+
export { default as WebFetcher } from "./WebFetcher.js";
|
|
16
|
+
export { default as Guard, GuardBlockedError } from "./Guard.js";
|
|
9
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,0EAA0E;AAC1E,kFAAkF;AAClF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,sEAAsE;AACtE,sEAAsE;AACtE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,0EAA0E;AAC1E,kFAAkF;AAClF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,+EAA+E;AAC/E,gFAAgF;AAChF,iEAAiE;AACjE,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAExC,sEAAsE;AACtE,sEAAsE;AACtE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC;AAGlD,wEAAwE;AACxE,6DAA6D;AAC7D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
package/docs/http.md
CHANGED
|
@@ -49,3 +49,5 @@ The `SEND[code]` is loop disposition (`102`/`200`/…), never the HTTP status
|
|
|
49
49
|
the real `2xx`/`4xx` comes back in `#header`.
|
|
50
50
|
|
|
51
51
|
Status: `102` streaming · `499` cancelled · `502` upstream/render failure.
|
|
52
|
+
|
|
53
|
+
For a persistent, bidirectional connection, see the `wss://` scheme.
|
package/docs/wss.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# wss:// — WebSocket
|
|
2
|
+
|
|
3
|
+
A full-duplex, persistent connection to a WebSocket origin. Unlike `http://`
|
|
4
|
+
(request/response) or SSE (a one-way `http://` event stream), a WebSocket is
|
|
5
|
+
**bidirectional and stateful**: you open it once, then send and receive on the
|
|
6
|
+
same live connection until it closes.
|
|
7
|
+
|
|
8
|
+
## Ops
|
|
9
|
+
|
|
10
|
+
| Op | Effect |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `READ(wss://host/path)` | Open the socket. Inbound frames stream into the `messages` channel as they arrive; the READ holds until the socket closes. |
|
|
13
|
+
| `SEND[200](wss://host/path):your message:` | Push a message onto the **already-open** socket. READ it first — a SEND with no open socket is a `409`. |
|
|
14
|
+
| `SEND[499](wss://host/path)` | Cancel: closes the open socket. |
|
|
15
|
+
| `KILL(wss://host/path)` | Close the open socket. |
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
<<READ(wss://echo.websocket.events)::READ
|
|
19
|
+
<<SEND[200](wss://echo.websocket.events):hello:SEND
|
|
20
|
+
<<KILL(wss://echo.websocket.events)::KILL
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
A READ returns `102 Processing` and the socket's inbound frames accumulate in the
|
|
24
|
+
`messages` channel across turns — read them as they land, the way you read any
|
|
25
|
+
streaming subscription. The connection stays open for concurrent `SEND`s until
|
|
26
|
+
you `KILL` it or the origin closes.
|
|
27
|
+
|
|
28
|
+
## Model
|
|
29
|
+
|
|
30
|
+
- **One socket per target, per workspace.** The connection a READ opens is keyed by
|
|
31
|
+
its path; a later SEND/KILL to the same target acts on that connection.
|
|
32
|
+
- **SSRF-guarded.** The target is resolved and checked before connecting — a
|
|
33
|
+
`ws://`/`wss://` into loopback, link-local, or RFC-1918/CGNAT space is refused
|
|
34
|
+
(`403`), the same guard the fetch path uses.
|
|
35
|
+
|
|
36
|
+
## Day-one limits
|
|
37
|
+
|
|
38
|
+
- **Text frames only.** Binary frames stringify loosely; structured binary is a
|
|
39
|
+
follow-up (#468).
|
|
40
|
+
- **No reconnection.** A dropped socket closes the READ; re-READ to reopen.
|
|
41
|
+
- **Default handshake identity.** Custom request headers on the WebSocket
|
|
42
|
+
handshake aren't wired yet (the standard `WebSocket` constructor has no header
|
|
43
|
+
slot); pending, tracked on #468.
|
|
44
|
+
|
|
45
|
+
Runtime: Node ≥22 (global `WebSocket`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plurnk/plurnk-schemes-http",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "http(s):// URI scheme handler for the plurnk agent runtime — fetch + streaming response body.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"plurnk",
|
|
@@ -28,7 +28,16 @@
|
|
|
28
28
|
},
|
|
29
29
|
"plurnk": {
|
|
30
30
|
"kind": "scheme",
|
|
31
|
-
"
|
|
31
|
+
"schemes": [
|
|
32
|
+
{
|
|
33
|
+
"name": "http",
|
|
34
|
+
"export": "default"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "wss",
|
|
38
|
+
"export": "Ws"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
32
41
|
},
|
|
33
42
|
"exports": {
|
|
34
43
|
".": {
|
|
@@ -58,6 +67,6 @@
|
|
|
58
67
|
"playwright": "1.61.1"
|
|
59
68
|
},
|
|
60
69
|
"peerDependencies": {
|
|
61
|
-
"@plurnk/plurnk-schemes": "1.0.
|
|
70
|
+
"@plurnk/plurnk-schemes": "1.0.7"
|
|
62
71
|
}
|
|
63
72
|
}
|