From e570fb46cff4b9a92cb1e615337764eac4e868d6 Mon Sep 17 00:00:00 2001 From: Kate Alpert <313617+kathrynalpert@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:43:39 -0600 Subject: [PATCH] Move Activities panel state from cookie to localStorage The Activities widget (XNAT.app.activityTab) persisted its state (the in-progress/completed task list plus the minimized flag) in a per-user cookie ("activities" + encoded username). Cookies are sent on every request, and the list only shrank on manual dismissal: start() added an entry but stopPoll() never removed finished ones, so the cookie grew with normal use. Stacked on the ~6 KB ALB auth cookie, it pushed request headers past Tomcat's maxHttpHeaderSize (default 8192), and Tomcat then rejected every request with HTTP 400 ("Request header is too large", thrown from Http11InputBuffer while parsing headers) until cookies were cleared. Nothing server-side reads this cookie; it exists only so the panel can repopulate and resume polling across page navigations, which localStorage does without riding the request headers. Swap the four persistence calls (get/set/remove) to localStorage, keeping the same key and JSON shape. Completed tasks are intentionally still kept so they remain reviewable after a reload. No legacy-cookie migration is included: that cookie has no expiry set, so it self-clears on browser close and stops growing as soon as this ships. Co-Authored-By: Claude Opus 4.8 --- .../webapp/scripts/xnat/app/activityTab.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/xnat-web/src/main/webapp/scripts/xnat/app/activityTab.js b/xnat-web/src/main/webapp/scripts/xnat/app/activityTab.js index 0ff2eca50..251ff85ae 100644 --- a/xnat-web/src/main/webapp/scripts/xnat/app/activityTab.js +++ b/xnat-web/src/main/webapp/scripts/xnat/app/activityTab.js @@ -24,7 +24,7 @@ var XNAT = getObject(XNAT); return factory(); } }(function(){ - let activityTab, cookieTag; + let activityTab, storageTag; const minimized = 'minimized', processes = 'processes'; @@ -33,12 +33,16 @@ var XNAT = getObject(XNAT); XNAT.app.activityTab = activityTab = getObject(XNAT.app.activityTab || {}); - XNAT.app.activityTab.cookieTag = cookieTag = 'activities' + XNAT.sub64.dlxEnc(window.username).encoded; + XNAT.app.activityTab.storageTag = storageTag = 'activities' + XNAT.sub64.dlxEnc(window.username).encoded; activityTab.pollers = []; function getActivities() { - return JSON.parse(XNAT.cookie.get(cookieTag) || '{"' + minimized + '": false, "' + processes + '": {}}'); + return JSON.parse(localStorage.getItem(storageTag) || '{"' + minimized + '": false, "' + processes + '": {}}'); + } + + function saveActivities(activities) { + localStorage.setItem(storageTag, JSON.stringify(activities)); } activityTab.init = function() { @@ -68,7 +72,7 @@ var XNAT = getObject(XNAT); timeout: timeout }; activities[processes][key] = item; - XNAT.cookie.set(cookieTag, activities, {}); + saveActivities(activities); activityTab.startPoll(item, key); }; @@ -108,12 +112,12 @@ var XNAT = getObject(XNAT); } } if ($.isEmptyObject(activities[processes])) { - XNAT.cookie.remove(cookieTag); + localStorage.removeItem(storageTag); const tab = $('#activity-tab'); tab.css('visibility', 'hidden'); tab.find('div.item').remove(); } else { - XNAT.cookie.set(cookieTag, activities, {}); + saveActivities(activities); } }; @@ -295,11 +299,11 @@ var XNAT = getObject(XNAT); return callback; } - function setMinimized(isMinimized, updateCookie) { + function setMinimized(isMinimized, updateStorage) { let activities = getActivities(); - if (updateCookie) { + if (updateStorage) { activities[minimized] = isMinimized; - XNAT.cookie.set(cookieTag, activities, {}); + saveActivities(activities); } if (isMinimized) { $('#activity-tab .panel-header span.count').text('(' + Object.keys(activities[processes]).length + ')');