@expo/serve-sim 0.3.2 → 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 +3 -0
- package/dist/middleware.js +85 -84
- package/dist/serve-sim.js +111 -110
- package/package.json +1 -1
- package/src/middleware.ts +35 -22
package/package.json
CHANGED
package/src/middleware.ts
CHANGED
|
@@ -24,7 +24,12 @@ import {
|
|
|
24
24
|
peekDeviceSession,
|
|
25
25
|
type HidSocket,
|
|
26
26
|
} from "./device-session";
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
acceptedTokenSubprotocol,
|
|
29
|
+
assertPreviewAccess,
|
|
30
|
+
assertUpgradeAccess,
|
|
31
|
+
upgradeAuthHeaders,
|
|
32
|
+
} from "./session-auth";
|
|
28
33
|
import {
|
|
29
34
|
eventLogEventForAction,
|
|
30
35
|
readEventLog,
|
|
@@ -654,26 +659,35 @@ function webSocketBinary(payload: Buffer<ArrayBufferLike>): Uint8Array<ArrayBuff
|
|
|
654
659
|
* handshake doesn't flush under Bun). Writes the 101 response and resumes the
|
|
655
660
|
* socket on success; on a missing key writes 400 and returns false.
|
|
656
661
|
*/
|
|
657
|
-
function writeWebSocketAccept(req: SimReq, socket: Socket): boolean {
|
|
662
|
+
function writeWebSocketAccept(req: SimReq, socket: Socket, execToken: string): boolean {
|
|
658
663
|
const key = req.headers["sec-websocket-key"];
|
|
659
664
|
if (typeof key !== "string") {
|
|
660
665
|
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
661
666
|
return false;
|
|
662
667
|
}
|
|
663
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);
|
|
664
671
|
socket.write(
|
|
665
672
|
"HTTP/1.1 101 Switching Protocols\r\n" +
|
|
666
673
|
"Upgrade: websocket\r\n" +
|
|
667
674
|
"Connection: Upgrade\r\n" +
|
|
668
675
|
`Sec-WebSocket-Accept: ${accept}\r\n` +
|
|
676
|
+
(subprotocol ? `Sec-WebSocket-Protocol: ${subprotocol}\r\n` : "") +
|
|
669
677
|
"\r\n",
|
|
670
678
|
);
|
|
671
679
|
socket.resume();
|
|
672
680
|
return true;
|
|
673
681
|
}
|
|
674
682
|
|
|
675
|
-
function bridgeWebSocketFrames(
|
|
676
|
-
|
|
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;
|
|
677
691
|
|
|
678
692
|
const upstream = new WebSocket(upstreamUrl);
|
|
679
693
|
upstream.binaryType = "arraybuffer";
|
|
@@ -971,6 +985,7 @@ function rawHidSocket(socket: Socket, head: Buffer): HidSocket {
|
|
|
971
985
|
function attachHidInProcess(
|
|
972
986
|
req: SimReq,
|
|
973
987
|
socket: Socket,
|
|
988
|
+
execToken: string,
|
|
974
989
|
head: Buffer,
|
|
975
990
|
device: string | null,
|
|
976
991
|
initialStreamSettings?: StreamSettings,
|
|
@@ -982,7 +997,7 @@ function attachHidInProcess(
|
|
|
982
997
|
} catch {
|
|
983
998
|
return false;
|
|
984
999
|
}
|
|
985
|
-
if (!writeWebSocketAccept(req, socket)) return true; // bad request handled
|
|
1000
|
+
if (!writeWebSocketAccept(req, socket, execToken)) return true; // bad request handled
|
|
986
1001
|
session.attachHidSocket(rawHidSocket(socket, head));
|
|
987
1002
|
return true;
|
|
988
1003
|
}
|
|
@@ -2665,13 +2680,7 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2665
2680
|
// their own, so gate them here too.
|
|
2666
2681
|
if (
|
|
2667
2682
|
!assertUpgradeAccess(
|
|
2668
|
-
|
|
2669
|
-
authorization: req.headers.authorization,
|
|
2670
|
-
cookie: req.headers.cookie,
|
|
2671
|
-
origin: req.headers.origin,
|
|
2672
|
-
host: req.headers.host,
|
|
2673
|
-
"sec-fetch-site": req.headers["sec-fetch-site"],
|
|
2674
|
-
},
|
|
2683
|
+
upgradeAuthHeaders(req.headers),
|
|
2675
2684
|
execToken,
|
|
2676
2685
|
{ required: requirePreviewToken },
|
|
2677
2686
|
)
|
|
@@ -2687,7 +2696,13 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2687
2696
|
(async () => {
|
|
2688
2697
|
try {
|
|
2689
2698
|
const bridge = await getInspectWebKitBridge();
|
|
2690
|
-
bridgeWebSocketFrames(
|
|
2699
|
+
bridgeWebSocketFrames(
|
|
2700
|
+
req,
|
|
2701
|
+
socket,
|
|
2702
|
+
head,
|
|
2703
|
+
`ws://127.0.0.1:${bridge.port}${devtoolsTarget.upstreamPath}`,
|
|
2704
|
+
execToken,
|
|
2705
|
+
);
|
|
2691
2706
|
} catch (err) {
|
|
2692
2707
|
const message = err instanceof Error ? err.message : "Failed to start inspect-webkit";
|
|
2693
2708
|
socket.end(`HTTP/1.1 502 Bad Gateway\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n${message}`);
|
|
@@ -2702,7 +2717,7 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2702
2717
|
const device = helperTarget.device ?? selectedDevice;
|
|
2703
2718
|
if (helperTarget.upstreamPath === "/ws") {
|
|
2704
2719
|
// HID input is delivered to the in-process DeviceSession.
|
|
2705
|
-
if (attachHidInProcess(req, socket, head, device, streamSettings)) return;
|
|
2720
|
+
if (attachHidInProcess(req, socket, execToken, head, device, streamSettings)) return;
|
|
2706
2721
|
socket.end("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
2707
2722
|
return;
|
|
2708
2723
|
}
|
|
@@ -2717,6 +2732,7 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2717
2732
|
const execWebSocketHandler = createExecWebSocketHandler({
|
|
2718
2733
|
path: `${base}/exec-ws`,
|
|
2719
2734
|
execToken,
|
|
2735
|
+
corsOrigins,
|
|
2720
2736
|
ssePrefixes: [
|
|
2721
2737
|
`${base}/api/events`,
|
|
2722
2738
|
`${base}/api/event-log/events`,
|
|
@@ -2740,17 +2756,14 @@ export function simMiddleware(options?: SimMiddlewareOptions): SimMiddleware {
|
|
|
2740
2756
|
});
|
|
2741
2757
|
|
|
2742
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());
|
|
2743
2762
|
// Embedded hosts forward accepted sockets and bypass the request gate. The exec channel
|
|
2744
|
-
// re-checks the token
|
|
2763
|
+
// re-checks the token itself; the helper HID socket does not.
|
|
2745
2764
|
if (
|
|
2746
2765
|
!assertUpgradeAccess(
|
|
2747
|
-
|
|
2748
|
-
authorization: request.headers.get("authorization") ?? undefined,
|
|
2749
|
-
cookie: request.headers.get("cookie") ?? undefined,
|
|
2750
|
-
origin: request.headers.get("origin") ?? undefined,
|
|
2751
|
-
host: request.headers.get("host") ?? undefined,
|
|
2752
|
-
"sec-fetch-site": request.headers.get("sec-fetch-site") ?? undefined,
|
|
2753
|
-
},
|
|
2766
|
+
upgradeAuthHeaders(request),
|
|
2754
2767
|
execToken,
|
|
2755
2768
|
{ required: requirePreviewToken },
|
|
2756
2769
|
)
|