diff --git a/src/utils/proxy/cookie-jar.js b/src/utils/proxy/cookie-jar.js index 66e00dca1..c7898d5c0 100644 --- a/src/utils/proxy/cookie-jar.js +++ b/src/utils/proxy/cookie-jar.js @@ -2,13 +2,13 @@ import { Cookie, CookieJar } from "tough-cookie"; const cookieJar = new CookieJar(); -export function setCookieHeader(url, params) { +export function setCookieHeader(url, params, { overwrite = false } = {}) { // add cookie header, if we have one in the jar const existingCookie = cookieJar.getCookieStringSync(url.toString()); if (existingCookie) { params.headers = params.headers ?? {}; const cookieHeader = params.cookieHeader ?? "Cookie"; - if (!params.headers[cookieHeader]) { + if (overwrite || !params.headers[cookieHeader]) { params.headers[cookieHeader] = existingCookie; } } diff --git a/src/utils/proxy/cookie-jar.test.js b/src/utils/proxy/cookie-jar.test.js index 83e459b3c..6676dc357 100644 --- a/src/utils/proxy/cookie-jar.test.js +++ b/src/utils/proxy/cookie-jar.test.js @@ -54,4 +54,17 @@ describe("utils/proxy/cookie-jar", () => { expect(params.headers.Cookie).toBe("manual=1"); }); + + it("overwrites an existing cookie header when requested", async () => { + const { addCookieToJar, setCookieHeader } = await import("./cookie-jar"); + + const url = new URL("http://example5.test/path"); + addCookieToJar(url, { "set-cookie": ["sid=1; Path=/"] }); + + const params = { headers: { Cookie: "stale=1" } }; + setCookieHeader(url, params, { overwrite: true }); + + expect(params.headers.Cookie).toContain("sid=1"); + expect(params.headers.Cookie).not.toContain("stale=1"); + }); }); diff --git a/src/utils/proxy/handlers/unifi.js b/src/utils/proxy/handlers/unifi.js index 6a2b43247..0c165c1ea 100644 --- a/src/utils/proxy/handlers/unifi.js +++ b/src/utils/proxy/handlers/unifi.js @@ -97,7 +97,7 @@ export default function createUnifiProxyHandler({ } addCookieToJar(url, responseHeaders); - setCookieHeader(url, params); + setCookieHeader(url, params, { overwrite: true }); [status, contentType, data, responseHeaders] = await httpProxy(url, params); } diff --git a/src/utils/proxy/http.js b/src/utils/proxy/http.js index 8cf50899f..5bea7e5f5 100644 --- a/src/utils/proxy/http.js +++ b/src/utils/proxy/http.js @@ -18,7 +18,7 @@ function addCookieHandler(url, params) { // handle cookies during redirects params.beforeRedirect = (options, responseInfo) => { addCookieToJar(options.href, responseInfo.headers); - setCookieHeader(options.href, options); + setCookieHeader(options.href, options, { overwrite: true }); }; } diff --git a/src/utils/proxy/http.test.js b/src/utils/proxy/http.test.js index 8f3cc0198..943b635d6 100644 --- a/src/utils/proxy/http.test.js +++ b/src/utils/proxy/http.test.js @@ -348,7 +348,9 @@ describe("utils/proxy/http httpProxy", () => { ); expect(cookieJar.addCookieToJar).toHaveBeenCalledWith("http://example.com/redirect", { "set-cookie": ["a=b"] }); - expect(cookieJar.setCookieHeader).toHaveBeenCalledWith("http://example.com/redirect", expect.any(Object)); + expect(cookieJar.setCookieHeader).toHaveBeenCalledWith("http://example.com/redirect", expect.any(Object), { + overwrite: true, + }); }); it("supports gzip-compressed responses", async () => { diff --git a/src/widgets/frigate/proxy.js b/src/widgets/frigate/proxy.js index 50f7c96d6..6e4c00c2b 100644 --- a/src/widgets/frigate/proxy.js +++ b/src/widgets/frigate/proxy.js @@ -1,7 +1,7 @@ import getServiceWidget from "utils/config/service-helpers"; import createLogger from "utils/logger"; import { asJson, formatApiCall, sanitizeErrorURL } from "utils/proxy/api-helpers"; -import { addCookieToJar } from "utils/proxy/cookie-jar"; +import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar"; import { httpProxy } from "utils/proxy/http"; import widgets from "widgets/widgets"; @@ -57,6 +57,7 @@ export default async function frigateProxyHandler(req, res, map) { } addCookieToJar(url, loginResponseHeaders); + setCookieHeader(url, params, { overwrite: true }); // Retry original request with cookie set [status, , data] = await httpProxy(url, params); } diff --git a/src/widgets/frigate/proxy.test.js b/src/widgets/frigate/proxy.test.js index 7b63bcdda..971128311 100644 --- a/src/widgets/frigate/proxy.test.js +++ b/src/widgets/frigate/proxy.test.js @@ -7,6 +7,7 @@ const { httpProxy, getServiceWidget, cookieJar, logger } = vi.hoisted(() => ({ getServiceWidget: vi.fn(), cookieJar: { addCookieToJar: vi.fn(), + setCookieHeader: vi.fn(), }, logger: { debug: vi.fn(), @@ -130,6 +131,9 @@ describe("widgets/frigate/proxy", () => { await frigateProxyHandler(req, res); expect(cookieJar.addCookieToJar).toHaveBeenCalled(); + expect(cookieJar.setCookieHeader).toHaveBeenCalledWith("http://frigate/api/stats", expect.any(Object), { + overwrite: true, + }); expect(res.statusCode).toBe(200); expect(res.body).toEqual({ num_cameras: 2, uptime: 123, version: "1.0" }); }); diff --git a/src/widgets/unifi/proxy.test.js b/src/widgets/unifi/proxy.test.js index 6d84821e0..455b02774 100644 --- a/src/widgets/unifi/proxy.test.js +++ b/src/widgets/unifi/proxy.test.js @@ -86,6 +86,9 @@ describe("widgets/unifi/proxy", () => { expect(httpProxy).toHaveBeenCalledTimes(4); expect(httpProxy.mock.calls[1][0].toString()).toContain("/proxy/network/api/self"); expect(cookieJar.addCookieToJar).toHaveBeenCalled(); + expect(cookieJar.setCookieHeader).toHaveBeenLastCalledWith(expect.any(URL), expect.any(Object), { + overwrite: true, + }); expect(res.statusCode).toBe(200); expect(res.body).toEqual(Buffer.from("data")); });