mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
fix(studio): Studio leaves cookies out of its requests only when served from loopback
This commit is contained in:
@@ -35,8 +35,11 @@ export function mountStudioApi(
|
||||
}
|
||||
```
|
||||
|
||||
Studio sends its API requests without cookies, so they don't queue behind the
|
||||
preview's media. A host that authenticates its mounted API with same-origin
|
||||
When it is served from loopback (`localhost`, `127.0.0.1` or `[::1]`), Studio
|
||||
sends its API requests without cookies, so they don't queue behind the
|
||||
preview's media. On any other origin it sends them as usual, so remote and
|
||||
proxied setups (Codespaces, tunnels, an access proxy) keep their cookies by
|
||||
default. A loopback host that authenticates its mounted API with same-origin
|
||||
cookies sets `VITE_STUDIO_API_SAME_ORIGIN_CREDENTIALS=true`, at build time or at
|
||||
runtime in `window.__HF_STUDIO_ENV__`; it costs that host the connection
|
||||
speedup.
|
||||
|
||||
@@ -28,7 +28,38 @@ describe("studioApiFetch", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("sends same-origin credentials for a host that opted out", async () => {
|
||||
it.each([
|
||||
["the CLI or Studio dev server", "http://localhost:5190/"],
|
||||
["Desktop's own server", "http://127.0.0.1:43117/"],
|
||||
["IPv6 loopback", "http://[::1]:8080/"],
|
||||
])("leaves cookies out when Studio is served from %s", async (_, page) => {
|
||||
const fetchMock = vi.fn(async () => new Response("ok"));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
vi.stubGlobal("location", new URL(page));
|
||||
const { studioApiFetch } = await loadWithEnv({});
|
||||
|
||||
await studioApiFetch("/api/projects/demo/files/index.html");
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith("/api/projects/demo/files/index.html", {
|
||||
credentials: "omit",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps same-origin cookies off loopback, where a proxy or tunnel may authenticate with them", async () => {
|
||||
const fetchMock = vi.fn(async () => new Response("ok"));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
vi.stubGlobal("location", new URL("https://studio.example.com/editor"));
|
||||
const { studioApiFetch } = await loadWithEnv({});
|
||||
|
||||
await studioApiFetch("/api/projects/demo/files/index.html");
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith("/api/projects/demo/files/index.html", {
|
||||
credentials: "same-origin",
|
||||
});
|
||||
});
|
||||
|
||||
it("sends same-origin credentials on loopback for a host that opted out", async () => {
|
||||
vi.stubGlobal("location", new URL("http://localhost:5190/"));
|
||||
const fetchMock = vi.fn(async () => new Response("ok"));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
const { studioApiFetch } = await loadWithEnv({
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import { STUDIO_API_SAME_ORIGIN_CREDENTIALS } from "../components/editor/manualEditingAvailability";
|
||||
|
||||
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
||||
|
||||
function studioApiCredentials(): RequestCredentials {
|
||||
if (STUDIO_API_SAME_ORIGIN_CREDENTIALS) return "same-origin";
|
||||
const host = globalThis.location?.hostname;
|
||||
return !host || LOOPBACK_HOSTS.has(host) ? "omit" : "same-origin";
|
||||
}
|
||||
|
||||
export function studioApiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
||||
return globalThis.fetch(input, {
|
||||
...init,
|
||||
credentials: STUDIO_API_SAME_ORIGIN_CREDENTIALS ? "same-origin" : "omit",
|
||||
});
|
||||
return globalThis.fetch(input, { ...init, credentials: studioApiCredentials() });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user