| 545 | } |
| 546 | |
| 547 | async function proxyLocalRequest(request) { |
| 548 | const target = new URL(request.path, `${localUrl}/`); |
| 549 | if (!target.searchParams.has("simdeckToken")) { |
| 550 | target.searchParams.set("simdeckToken", localToken); |
| 551 | } |
| 552 | const headers = new Headers(request.headers || {}); |
| 553 | headers.set("x-simdeck-token", localToken); |
| 554 | headers.delete("host"); |
| 555 | headers.delete("content-length"); |
| 556 | let response; |
| 557 | try { |
| 558 | response = await fetch(target, { |
| 559 | body: request.bodyBase64 |
| 560 | ? Buffer.from(request.bodyBase64, "base64") |
| 561 | : undefined, |
| 562 | headers, |
| 563 | method: request.method, |
| 564 | signal: AbortSignal.timeout(proxyTimeoutMs), |
| 565 | }); |
| 566 | } catch (error) { |
| 567 | throw new Error( |
| 568 | `Local SimDeck request ${target.origin}${target.pathname} failed`, |
| 569 | { |
| 570 | cause: error, |
| 571 | }, |
| 572 | ); |
| 573 | } |
| 574 | const responseHeaders = {}; |
| 575 | for (const [name, value] of response.headers.entries()) { |
| 576 | const lower = name.toLowerCase(); |
| 577 | if ( |
| 578 | lower === "connection" || |
| 579 | lower === "content-encoding" || |
| 580 | lower === "content-length" || |
| 581 | lower === "transfer-encoding" |
| 582 | ) { |
| 583 | continue; |
| 584 | } |
| 585 | responseHeaders[name] = value; |
| 586 | } |
| 587 | const responseBodyBase64 = Buffer.from(await response.arrayBuffer()).toString( |
| 588 | "base64", |
| 589 | ); |
| 590 | return { |
| 591 | responseStatus: response.status, |
| 592 | responseHeaders, |
| 593 | responseBodyBase64, |
| 594 | }; |
| 595 | } |
| 596 | |
| 597 | async function handleLocalProxyFailure(error) { |
| 598 | const message = describeError(error); |