From 4707c6444e812e73023d98b7b2059338b4a7b2af Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Tue, 24 Mar 2026 21:59:50 +0200 Subject: [PATCH] fix(rgi): rgiDownload handles session expiry + re-login on 401/302/404 eTerra returns 404 (not 401) when session expires during file download because it redirects to login page. Now rgiDownload: - Uses validateStatus to catch all statuses - Re-logins and retries on 401/302/404 - Sets Accept: */* header for binary downloads Co-Authored-By: Claude Opus 4.6 (1M context) --- .../parcel-sync/services/eterra-client.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/modules/parcel-sync/services/eterra-client.ts b/src/modules/parcel-sync/services/eterra-client.ts index 7972548..5206aec 100644 --- a/src/modules/parcel-sync/services/eterra-client.ts +++ b/src/modules/parcel-sync/services/eterra-client.ts @@ -1015,17 +1015,34 @@ export class EterraClient { */ async rgiDownload(path: string): Promise<{ data: Buffer; contentType: string; filename: string }> { const url = `${BASE_URL}/api/${path}`; - const response = await this.requestWithRetry(() => + const doRequest = () => this.client.get(url, { timeout: this.timeoutMs, responseType: "arraybuffer", - }), - ); - const cd = (response as { headers?: Record }).headers?.["content-disposition"] ?? ""; + // Override Accept header for binary download + headers: { Accept: "*/*" }, + // Don't throw on any status — we'll check manually + validateStatus: () => true, + }); + + let response = await doRequest(); + + // If 401/302/404 (session expired → redirect to login), re-login and retry + if (response.status === 401 || response.status === 302 || response.status === 404) { + await this.login(this.username, this.password); + response = await doRequest(); + } + + if (response.status !== 200) { + throw new Error(`Download failed: HTTP ${response.status}`); + } + + const headers = response.headers as Record | undefined; + const cd = headers?.["content-disposition"] ?? ""; const match = /filename="?([^"]+)"?/.exec(cd); return { data: Buffer.from(response.data as ArrayBuffer), - contentType: (response as { headers?: Record }).headers?.["content-type"] ?? "application/octet-stream", + contentType: headers?.["content-type"] ?? "application/octet-stream", filename: match?.[1] ?? "document.pdf", }; }