diff --git a/js/http_fetcher.js b/js/http_fetcher.js index b2d7b8c083..eca4896080 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -32,7 +32,7 @@ const ERROR_TYPE_TO_TRANSLATION = { * - Authentication support (Basic, Bearer) * - Self-signed certificate support * @augments EventEmitter - * @fires HTTPFetcher#response - When fetch succeeds with ok response + * @fires HTTPFetcher#response - When fetch succeeds (including 304 Not Modified) * @fires HTTPFetcher#error - When fetch fails or returns non-ok response * @example * const fetcher = new HTTPFetcher(url, { reloadInterval: 60000 }); @@ -295,21 +295,21 @@ class HTTPFetcher extends EventEmitter { const isSuccessfulResponse = response.ok || response.status === 304; - if (!isSuccessfulResponse) { - const { delay, errorInfo } = this.#getDelayForResponse(response); - nextDelay = delay; - this.emit("error", errorInfo); - } else { + if (isSuccessfulResponse) { // Reset error counts on success this.serverErrorCount = 0; this.networkErrorCount = 0; /** - * Response event - fired when fetch succeeds + * Response event - fired when fetch succeeds (including 304) * @event HTTPFetcher#response * @type {Response} */ this.emit("response", response); + } else { + const { delay, errorInfo } = this.#getDelayForResponse(response); + nextDelay = delay; + this.emit("error", errorInfo); } } catch (error) { const isTimeout = error.name === "AbortError"; diff --git a/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js index 122025a26c..5162fb760a 100644 --- a/tests/unit/functions/http_fetcher_spec.js +++ b/tests/unit/functions/http_fetcher_spec.js @@ -51,31 +51,6 @@ describe("HTTPFetcher", () => { expect(text).toBe(responseData); }); - it("should treat 304 responses as successful and reset error counters", async () => { - server.use( - http.get(TEST_URL, () => { - return new HttpResponse(null, { status: 304 }); - }) - ); - - fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); - fetcher.serverErrorCount = 2; - fetcher.networkErrorCount = 3; - - const responsePromise = new Promise((resolve) => { - fetcher.on("response", (response) => { - resolve(response); - }); - }); - - fetcher.startPeriodicFetch(); - const response = await responsePromise; - - expect(response.status).toBe(304); - expect(fetcher.serverErrorCount).toBe(0); - expect(fetcher.networkErrorCount).toBe(0); - }); - it("should emit error event on network failure", async () => { server.use( http.get(TEST_URL, () => { @@ -126,6 +101,34 @@ describe("HTTPFetcher", () => { }); describe("HTTPFetcher - HTTP status code handling", () => { + describe("304 Not Modified", () => { + it("should emit response event for 304 and not emit error", async () => { + server.use( + http.get(TEST_URL, () => { + return new HttpResponse(null, { status: 304 }); + }) + ); + + fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 }); + fetcher.serverErrorCount = 2; + fetcher.networkErrorCount = 3; + + const responsePromise = new Promise((resolve) => { + fetcher.on("response", resolve); + }); + const errorSpy = vi.fn(); + fetcher.on("error", errorSpy); + + fetcher.startPeriodicFetch(); + const response = await responsePromise; + + expect(response.status).toBe(304); + expect(errorSpy).not.toHaveBeenCalled(); + expect(fetcher.serverErrorCount).toBe(0); + expect(fetcher.networkErrorCount).toBe(0); + }); + }); + describe("401/403 errors (Auth failures)", () => { it("should emit error with AUTH_FAILURE for 401", async () => { server.use(