@expo/serve-sim 0.3.1 → 0.3.3
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/README.md +7 -3
- package/dist/middleware.js +110 -98
- package/dist/native/serve-sim-native.node +0 -0
- package/dist/serve-sim.js +149 -137
- package/package.json +1 -1
- package/src/middleware.ts +183 -71
package/package.json
CHANGED
package/src/middleware.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { openSseStream } from "./sse-stream";
|
|
2
|
+
import { execFile, execSync } from "child_process";
|
|
2
3
|
import { readdirSync, readFileSync, existsSync, unlinkSync, watch, type FSWatcher } from "fs";
|
|
3
4
|
import { readFile, unlink } from "fs/promises";
|
|
4
5
|
import { tmpdir } from "os";
|
|
@@ -23,7 +24,12 @@ import {
|
|
|
23
24
|
peekDeviceSession,
|
|
24
25
|
type HidSocket,
|
|
25
26
|
} from "./device-session";
|
|
26
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
acceptedTokenSubprotocol,
|
|
29
|
+
assertPreviewAccess,
|
|
30
|
+
assertUpgradeAccess,
|
|
31
|
+
upgradeAuthHeaders,
|
|
32
|
+
} from "./session-auth";
|
|
27
33
|
import {
|
|
28
34
|
eventLogEventForAction,
|
|
29
35
|
readEventLog,
|
|
@@ -42,6 +48,11 @@ import {
|
|
|
42
48
|
import { serveDeviceKitModelAsset } from "./devicekit-model";
|
|
43
49
|
import { validatePanelRoute } from "./panel-route";
|
|
44
50
|
import { createExecWebSocketHandler, type UiRequestHandler } from "./exec-ws";
|
|
51
|
+
import { crashRuntime } from "./crash/runtime";
|
|
52
|
+
import { handleCrashesRequestAfter, handleCrashReportRequest } from "./crash/routes";
|
|
53
|
+
export { handleCrashesRequest, handleCrashReportRequest } from "./crash/routes";
|
|
54
|
+
import { booleanParam } from "./request-params";
|
|
55
|
+
import { logBufferCache, type LogBufferCache, type LogLine } from "./log-buffer";
|
|
45
56
|
import { claimHelperHidSocket, type UpgradeHandlerWebSocket } from "./middleware-utils";
|
|
46
57
|
import { UI_OPTIONS, getUiStatus, normalizeUiValue, setUiOption } from "./ui-settings";
|
|
47
58
|
import { type WebMiddleware } from "./runtime-utils";
|
|
@@ -128,10 +139,6 @@ const metricsSamplerCache = createMetricsSamplerCache(
|
|
|
128
139
|
(udid) => new MetricsSampler({ udid, deviceName: bootedDeviceName(udid) }),
|
|
129
140
|
);
|
|
130
141
|
|
|
131
|
-
// Hard cap on the SSE line-assembly buffer for child-process stdout.
|
|
132
|
-
// A malformed log entry without a newline can't grow this beyond 1 MB;
|
|
133
|
-
// the partial line is dropped rather than retained indefinitely.
|
|
134
|
-
const SSE_LINE_BUFFER_LIMIT = 1024 * 1024;
|
|
135
142
|
let inspectWebKitBridge: Promise<WebKitBridge> | null = null;
|
|
136
143
|
|
|
137
144
|
function eventLogLimit(rawUrl: string): number | undefined {
|
|
@@ -254,7 +261,8 @@ export function matchInstalledAppByDisplayName(
|
|
|
254
261
|
|
|
255
262
|
// Cache simctl's booted-device set briefly so per-request cost stays bounded.
|
|
256
263
|
// The middleware runs inside the user's dev server (Metro etc.) and
|
|
257
|
-
//
|
|
264
|
+
// The window has to outlast the logs drawer's poll interval.
|
|
265
|
+
const BOOTED_CACHE_TTL_MS = 5_000;
|
|
258
266
|
let bootedSnapshot: {
|
|
259
267
|
at: number;
|
|
260
268
|
booted: Set<string> | null;
|
|
@@ -268,7 +276,7 @@ let bootedSnapshot: {
|
|
|
268
276
|
};
|
|
269
277
|
async function getBootedUdids(): Promise<Set<string> | null> {
|
|
270
278
|
const now = Date.now();
|
|
271
|
-
if (bootedSnapshot.booted && now - bootedSnapshot.at <
|
|
279
|
+
if (bootedSnapshot.booted && now - bootedSnapshot.at < BOOTED_CACHE_TTL_MS) {
|
|
272
280
|
return bootedSnapshot.booted;
|
|
273
281
|
}
|
|
274
282
|
try {
|
|
@@ -651,26 +659,35 @@ function webSocketBinary(payload: Buffer<ArrayBufferLike>): Uint8Array<ArrayBuff
|
|
|
651
659
|
* handshake doesn't flush under Bun). Writes the 101 response and resumes the
|
|
652
660
|
* socket on success; on a missing key writes 400 and returns false.
|
|
653
661
|
*/
|
|
654
|
-
function writeWebSocketAccept(req: SimReq, socket: Socket): boolean {
|
|
662
|
+
function writeWebSocketAccept(req: SimReq, socket: Socket, execToken: string): boolean {
|
|
655
663
|
const key = req.headers["sec-websocket-key"];
|
|
656
664
|
if (typeof key !== "string") {
|
|
657
665
|
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
658
666
|
return false;
|
|
659
667
|
}
|
|
660
668
|
const accept = createHash("sha1").update(key + WS_ACCEPT_GUID).digest("base64");
|
|
669
|
+
// A client that offered subprotocols fails the handshake unless one is named back.
|
|
670
|
+
const subprotocol = acceptedTokenSubprotocol(req.headers, execToken);
|
|
661
671
|
socket.write(
|
|
662
672
|
"HTTP/1.1 101 Switching Protocols\r\n" +
|
|
663
673
|
"Upgrade: websocket\r\n" +
|
|
664
674
|
"Connection: Upgrade\r\n" +
|
|
665
675
|
`Sec-WebSocket-Accept: ${accept}\r\n` +
|
|
676
|
+
(subprotocol ? `Sec-WebSocket-Protocol: ${subprotocol}\r\n` : "") +
|
|
666
677
|
"\r\n",
|
|
667
678
|
);
|
|
668
679
|
socket.resume();
|
|
669
680
|
return true;
|
|
670
681
|
}
|
|
671
682
|
|
|
672
|
-
function bridgeWebSocketFrames(
|
|
673
|
-
|
|
683
|
+
function bridgeWebSocketFrames(
|
|
684
|
+
req: SimReq,
|
|
685
|
+
socket: Socket,
|
|
686
|
+
head: Buffer,
|
|
687
|
+
upstreamUrl: string,
|
|
688
|
+
execToken: string,
|
|
689
|
+
): void {
|
|
690
|
+
if (!writeWebSocketAccept(req, socket, execToken)) return;
|
|
674
691
|
|
|
675
692
|
const upstream = new WebSocket(upstreamUrl);
|
|
676
693
|
upstream.binaryType = "arraybuffer";
|
|
@@ -968,6 +985,7 @@ function rawHidSocket(socket: Socket, head: Buffer): HidSocket {
|
|
|
968
985
|
function attachHidInProcess(
|
|
969
986
|
req: SimReq,
|
|
970
987
|
socket: Socket,
|
|
988
|
+
execToken: string,
|
|
971
989
|
head: Buffer,
|
|
972
990
|
device: string | null,
|
|
973
991
|
initialStreamSettings?: StreamSettings,
|
|
@@ -979,7 +997,7 @@ function attachHidInProcess(
|
|
|
979
997
|
} catch {
|
|
980
998
|
return false;
|
|
981
999
|
}
|
|
982
|
-
if (!writeWebSocketAccept(req, socket)) return true; // bad request handled
|
|
1000
|
+
if (!writeWebSocketAccept(req, socket, execToken)) return true; // bad request handled
|
|
983
1001
|
session.attachHidSocket(rawHidSocket(socket, head));
|
|
984
1002
|
return true;
|
|
985
1003
|
}
|
|
@@ -995,6 +1013,7 @@ export function previewConfigForState(
|
|
|
995
1013
|
): ServeSimState & {
|
|
996
1014
|
basePath: string;
|
|
997
1015
|
logsEndpoint: string;
|
|
1016
|
+
crashesEndpoint: string;
|
|
998
1017
|
appStateEndpoint: string;
|
|
999
1018
|
eventLogEndpoint: string;
|
|
1000
1019
|
eventLogEventsEndpoint: string;
|
|
@@ -1033,6 +1052,7 @@ export function previewConfigForState(
|
|
|
1033
1052
|
...publicState,
|
|
1034
1053
|
basePath: base,
|
|
1035
1054
|
logsEndpoint: endpoint(base, "/logs", state.device),
|
|
1055
|
+
crashesEndpoint: endpoint(base, "/crashes", state.device),
|
|
1036
1056
|
appStateEndpoint: endpoint(base, "/appstate", state.device),
|
|
1037
1057
|
eventLogEndpoint: endpoint(base, "/api/event-log", state.device),
|
|
1038
1058
|
eventLogEventsEndpoint: endpoint(base, "/api/event-log/events", state.device),
|
|
@@ -1549,13 +1569,103 @@ function httpStreamSettingsFromLegacyCodec(codec: string | undefined): StreamSet
|
|
|
1549
1569
|
return undefined;
|
|
1550
1570
|
}
|
|
1551
1571
|
|
|
1572
|
+
|
|
1573
|
+
export function handleLogsRequest(
|
|
1574
|
+
req: SimReq,
|
|
1575
|
+
res: SimRes,
|
|
1576
|
+
state: ServeSimState | null,
|
|
1577
|
+
rawUrl: string,
|
|
1578
|
+
cache: LogBufferCache = logBufferCache
|
|
1579
|
+
): void {
|
|
1580
|
+
if (!state) {
|
|
1581
|
+
res.writeHead(404, { "Content-Type": "application/json", "Cache-Control": "no-store" });
|
|
1582
|
+
res.end(JSON.stringify({ error: "No serve-sim device" }));
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
const params = new URL(rawUrl, "http://127.0.0.1").searchParams;
|
|
1587
|
+
const intQuery = (name: string): number | undefined => {
|
|
1588
|
+
const raw = params.get(name)?.trim();
|
|
1589
|
+
const n = Number(raw);
|
|
1590
|
+
return raw && Number.isSafeInteger(n) && n >= 0 ? n : undefined;
|
|
1591
|
+
};
|
|
1592
|
+
const since = intQuery("since");
|
|
1593
|
+
const limit = intQuery("limit");
|
|
1594
|
+
const snapshot = params.get("snapshot");
|
|
1595
|
+
const wantsJson =
|
|
1596
|
+
snapshot === null
|
|
1597
|
+
? (req.headers.accept ?? "").includes("application/json")
|
|
1598
|
+
: booleanParam(params, "snapshot");
|
|
1599
|
+
const wantsEnvelope = booleanParam(params, "envelope");
|
|
1600
|
+
const wantsFollow = booleanParam(params, "follow");
|
|
1601
|
+
|
|
1602
|
+
if (wantsJson) {
|
|
1603
|
+
const buffer = wantsFollow ? cache.ensure(state.device) : cache.peek(state.device);
|
|
1604
|
+
res.writeHead(200, { "Content-Type": "application/json", "Cache-Control": "no-store" });
|
|
1605
|
+
res.end(
|
|
1606
|
+
JSON.stringify({
|
|
1607
|
+
device: state.device,
|
|
1608
|
+
latestSeq: buffer?.latestSeq ?? 0,
|
|
1609
|
+
oldestSeq: buffer?.oldestSeq ?? 0,
|
|
1610
|
+
bufferedBytes: buffer?.byteLength ?? 0,
|
|
1611
|
+
status: buffer?.status ?? "stopped",
|
|
1612
|
+
streamError: buffer?.error ?? null,
|
|
1613
|
+
lines: buffer?.read({ since, limit }) ?? [],
|
|
1614
|
+
})
|
|
1615
|
+
);
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
const buffer = cache.ensure(state.device);
|
|
1620
|
+
const stream = openSseStream(req, res);
|
|
1621
|
+
|
|
1622
|
+
const frame = (line: LogLine): string =>
|
|
1623
|
+
"data: " +
|
|
1624
|
+
(wantsEnvelope ? JSON.stringify({ seq: line.seq, at: line.at, raw: line.raw }) : line.raw) +
|
|
1625
|
+
"\n\n";
|
|
1626
|
+
|
|
1627
|
+
let lastSent = since ?? 0;
|
|
1628
|
+
for (const line of buffer.read({ since, limit })) {
|
|
1629
|
+
if (!stream.isOpen()) break;
|
|
1630
|
+
stream.write(frame(line));
|
|
1631
|
+
lastSent = line.seq;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
stream.onClose(
|
|
1635
|
+
buffer.subscribeBatch(
|
|
1636
|
+
(lines) => {
|
|
1637
|
+
let chunk = "";
|
|
1638
|
+
for (const line of lines) {
|
|
1639
|
+
if (line.seq <= lastSent) continue;
|
|
1640
|
+
lastSent = line.seq;
|
|
1641
|
+
chunk += frame(line);
|
|
1642
|
+
}
|
|
1643
|
+
if (chunk) stream.write(chunk);
|
|
1644
|
+
},
|
|
1645
|
+
() => {
|
|
1646
|
+
if (stream.isOpen()) res.end();
|
|
1647
|
+
}
|
|
1648
|
+
)
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
async function selectDeviceAndReap(selectedDevice: string | null): Promise<ServeSimState | null> {
|
|
1653
|
+
const states = await readServeSimStates();
|
|
1654
|
+
const state = selectServeSimState(states, selectedDevice);
|
|
1655
|
+
const live = states.map((s) => s.device);
|
|
1656
|
+
crashRuntime.prune(live);
|
|
1657
|
+
logBufferCache.prune(live);
|
|
1658
|
+
return state;
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1552
1661
|
/**
|
|
1553
1662
|
* Connect-style middleware that serves the simulator preview UI.
|
|
1554
1663
|
*
|
|
1555
1664
|
* Routes handled under `basePath` (default `/.sim`):
|
|
1556
1665
|
* GET {basePath} — the preview HTML page
|
|
1557
1666
|
* GET {basePath}/api — serve-sim state JSON
|
|
1558
|
-
* GET {basePath}/logs —
|
|
1667
|
+
* GET {basePath}/logs — simctl logs, JSON snapshot or SSE (bearer token)
|
|
1668
|
+
* GET {basePath}/crashes — crash reports (bearer token)
|
|
1559
1669
|
* GET {basePath}/ax — SSE stream of normalized accessibility snapshots
|
|
1560
1670
|
*/
|
|
1561
1671
|
export function handleMetricsRequest(
|
|
@@ -1615,6 +1725,8 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
1615
1725
|
? { "Content-Security-Policy": frameAncestorsPolicy(frameAncestors) }
|
|
1616
1726
|
: {};
|
|
1617
1727
|
|
|
1728
|
+
crashRuntime.arm();
|
|
1729
|
+
|
|
1618
1730
|
// Simulator-settings requests run in-process (just the underlying simctl /
|
|
1619
1731
|
// ax-tool spawn) instead of round-tripping a full `node <cli>` exec per
|
|
1620
1732
|
// sidebar interaction.
|
|
@@ -2434,50 +2546,51 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2434
2546
|
return;
|
|
2435
2547
|
}
|
|
2436
2548
|
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
res
|
|
2443
|
-
|
|
2549
|
+
if (url === base + "/crashes" || url === base + "/crashes/") {
|
|
2550
|
+
const state = await selectDeviceAndReap(selectedDevice);
|
|
2551
|
+
await handleCrashesRequestAfter(
|
|
2552
|
+
() => crashRuntime.start({ deferToRetry: true }).catch(() => {}),
|
|
2553
|
+
req,
|
|
2554
|
+
res,
|
|
2555
|
+
state,
|
|
2556
|
+
rawUrl
|
|
2557
|
+
);
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
if (url.startsWith(base + "/crashes/")) {
|
|
2562
|
+
const rawId = url.slice((base + "/crashes/").length);
|
|
2563
|
+
let id: string;
|
|
2564
|
+
try {
|
|
2565
|
+
id = decodeURIComponent(rawId);
|
|
2566
|
+
} catch {
|
|
2567
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2568
|
+
res.end(
|
|
2569
|
+
JSON.stringify({
|
|
2570
|
+
error:
|
|
2571
|
+
`Malformed percent-escape in the crash id (${rawId}). Copy the id verbatim from ` +
|
|
2572
|
+
"GET {base}/crashes.",
|
|
2573
|
+
})
|
|
2574
|
+
);
|
|
2444
2575
|
return;
|
|
2445
2576
|
}
|
|
2446
|
-
const
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
"
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
let buf = "";
|
|
2462
|
-
child.stdout!.on("data", (chunk: Buffer) => {
|
|
2463
|
-
buf += chunk.toString();
|
|
2464
|
-
let nl: number;
|
|
2465
|
-
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
2466
|
-
const line = buf.slice(0, nl).trim();
|
|
2467
|
-
buf = buf.slice(nl + 1);
|
|
2468
|
-
if (line) res.write("data: " + line + "\n\n");
|
|
2469
|
-
}
|
|
2470
|
-
// Drop a runaway partial line so a malformed/never-terminated
|
|
2471
|
-
// log entry can't grow `buf` without bound.
|
|
2472
|
-
if (buf.length > SSE_LINE_BUFFER_LIMIT) buf = "";
|
|
2473
|
-
});
|
|
2577
|
+
const state = await selectDeviceAndReap(selectedDevice);
|
|
2578
|
+
const params = new URL(rawUrl, "http://127.0.0.1").searchParams;
|
|
2579
|
+
await handleCrashReportRequest(
|
|
2580
|
+
req,
|
|
2581
|
+
res,
|
|
2582
|
+
state,
|
|
2583
|
+
id,
|
|
2584
|
+
params.get("occurrence"),
|
|
2585
|
+
undefined,
|
|
2586
|
+
undefined,
|
|
2587
|
+
params.get("key")
|
|
2588
|
+
);
|
|
2589
|
+
return;
|
|
2590
|
+
}
|
|
2474
2591
|
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
req.on("close", () => {
|
|
2478
|
-
child.stdout?.destroy();
|
|
2479
|
-
child.kill();
|
|
2480
|
-
});
|
|
2592
|
+
if (url === base + "/logs") {
|
|
2593
|
+
handleLogsRequest(req, res, await selectDeviceAndReap(selectedDevice), rawUrl);
|
|
2481
2594
|
return;
|
|
2482
2595
|
}
|
|
2483
2596
|
|
|
@@ -2567,13 +2680,7 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2567
2680
|
// their own, so gate them here too.
|
|
2568
2681
|
if (
|
|
2569
2682
|
!assertUpgradeAccess(
|
|
2570
|
-
|
|
2571
|
-
authorization: req.headers.authorization,
|
|
2572
|
-
cookie: req.headers.cookie,
|
|
2573
|
-
origin: req.headers.origin,
|
|
2574
|
-
host: req.headers.host,
|
|
2575
|
-
"sec-fetch-site": req.headers["sec-fetch-site"],
|
|
2576
|
-
},
|
|
2683
|
+
upgradeAuthHeaders(req.headers),
|
|
2577
2684
|
execToken,
|
|
2578
2685
|
{ required: requirePreviewToken },
|
|
2579
2686
|
)
|
|
@@ -2589,7 +2696,13 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2589
2696
|
(async () => {
|
|
2590
2697
|
try {
|
|
2591
2698
|
const bridge = await getInspectWebKitBridge();
|
|
2592
|
-
bridgeWebSocketFrames(
|
|
2699
|
+
bridgeWebSocketFrames(
|
|
2700
|
+
req,
|
|
2701
|
+
socket,
|
|
2702
|
+
head,
|
|
2703
|
+
`ws://127.0.0.1:${bridge.port}${devtoolsTarget.upstreamPath}`,
|
|
2704
|
+
execToken,
|
|
2705
|
+
);
|
|
2593
2706
|
} catch (err) {
|
|
2594
2707
|
const message = err instanceof Error ? err.message : "Failed to start inspect-webkit";
|
|
2595
2708
|
socket.end(`HTTP/1.1 502 Bad Gateway\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n${message}`);
|
|
@@ -2604,7 +2717,7 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2604
2717
|
const device = helperTarget.device ?? selectedDevice;
|
|
2605
2718
|
if (helperTarget.upstreamPath === "/ws") {
|
|
2606
2719
|
// HID input is delivered to the in-process DeviceSession.
|
|
2607
|
-
if (attachHidInProcess(req, socket, head, device, streamSettings)) return;
|
|
2720
|
+
if (attachHidInProcess(req, socket, execToken, head, device, streamSettings)) return;
|
|
2608
2721
|
socket.end("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
2609
2722
|
return;
|
|
2610
2723
|
}
|
|
@@ -2619,12 +2732,14 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2619
2732
|
const execWebSocketHandler = createExecWebSocketHandler({
|
|
2620
2733
|
path: `${base}/exec-ws`,
|
|
2621
2734
|
execToken,
|
|
2735
|
+
corsOrigins,
|
|
2622
2736
|
ssePrefixes: [
|
|
2623
2737
|
`${base}/api/events`,
|
|
2624
2738
|
`${base}/api/event-log/events`,
|
|
2625
2739
|
`${base}/grid/api/status/events`,
|
|
2626
2740
|
`${base}/appstate`,
|
|
2627
2741
|
`${base}/logs`,
|
|
2742
|
+
`${base}/crashes`,
|
|
2628
2743
|
`${base}/metrics`,
|
|
2629
2744
|
`${base}/ax`,
|
|
2630
2745
|
],
|
|
@@ -2641,17 +2756,14 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2641
2756
|
});
|
|
2642
2757
|
|
|
2643
2758
|
fetchMiddleware.handleWebSocket = (request: Request, websocket: UpgradeHandlerWebSocket): boolean => {
|
|
2759
|
+
// Before any refusal below can close it: an unhandled error from a peer that keeps sending
|
|
2760
|
+
// would exit the process.
|
|
2761
|
+
websocket.on("error", () => websocket.close());
|
|
2644
2762
|
// Embedded hosts forward accepted sockets and bypass the request gate. The exec channel
|
|
2645
|
-
// re-checks the token
|
|
2763
|
+
// re-checks the token itself; the helper HID socket does not.
|
|
2646
2764
|
if (
|
|
2647
2765
|
!assertUpgradeAccess(
|
|
2648
|
-
|
|
2649
|
-
authorization: request.headers.get("authorization") ?? undefined,
|
|
2650
|
-
cookie: request.headers.get("cookie") ?? undefined,
|
|
2651
|
-
origin: request.headers.get("origin") ?? undefined,
|
|
2652
|
-
host: request.headers.get("host") ?? undefined,
|
|
2653
|
-
"sec-fetch-site": request.headers.get("sec-fetch-site") ?? undefined,
|
|
2654
|
-
},
|
|
2766
|
+
upgradeAuthHeaders(request),
|
|
2655
2767
|
execToken,
|
|
2656
2768
|
{ required: requirePreviewToken },
|
|
2657
2769
|
)
|