Use fetch() in a way that works for file URLs (#3071)

fetch returns a response code of 0 when it successfully loads a `file://` resource.

This means we can't just rely on `response.ok`.

Required for https://github.com/element-hq/element-call/issues/2994
This commit is contained in:
Hugh Nimmo-Smith
2025-03-11 09:39:51 +00:00
committed by GitHub
parent 2885e7e42e
commit 1a692b983a
5 changed files with 64 additions and 5 deletions

30
src/utils/fetch.test.ts Normal file
View File

@@ -0,0 +1,30 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { expect, describe, it } from "vitest";
import { isFailure } from "./fetch";
describe("isFailure", () => {
it("returns false for a successful response", () => {
expect(isFailure({ ok: true, url: "https://foo.com" } as Response)).toBe(
false,
);
});
it("returns true for a failed response", () => {
expect(isFailure({ ok: false, url: "https://foo.com" } as Response)).toBe(
true,
);
});
it("returns false for a file:// URL with status 0", () => {
expect(
isFailure({ ok: false, url: "file://foo", status: 0 } as Response),
).toBe(false);
});
});

25
src/utils/fetch.ts Normal file
View File

@@ -0,0 +1,25 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
/**
* Check if a fetch response is a failure in a way that works with file:// URLs
* @param response the response to check
* @returns true if the response is a failure, false otherwise
*/
export function isFailure(response: Response): boolean {
// if response says it's okay, then it's not a failure
if (response.ok) {
return false;
}
// fetch will return status === 0 for a success on a file:// URL, so we special case it
if (response.url.startsWith("file:") && response.status === 0) {
return false;
}
return true;
}