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) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-24 21:59:50 +02:00
parent e5e2fabb1d
commit 4707c6444e
@@ -1015,17 +1015,34 @@ export class EterraClient {
*/ */
async rgiDownload(path: string): Promise<{ data: Buffer; contentType: string; filename: string }> { async rgiDownload(path: string): Promise<{ data: Buffer; contentType: string; filename: string }> {
const url = `${BASE_URL}/api/${path}`; const url = `${BASE_URL}/api/${path}`;
const response = await this.requestWithRetry(() => const doRequest = () =>
this.client.get(url, { this.client.get(url, {
timeout: this.timeoutMs, timeout: this.timeoutMs,
responseType: "arraybuffer", responseType: "arraybuffer",
}), // Override Accept header for binary download
); headers: { Accept: "*/*" },
const cd = (response as { headers?: Record<string, string> }).headers?.["content-disposition"] ?? ""; // 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<string, string> | undefined;
const cd = headers?.["content-disposition"] ?? "";
const match = /filename="?([^"]+)"?/.exec(cd); const match = /filename="?([^"]+)"?/.exec(cd);
return { return {
data: Buffer.from(response.data as ArrayBuffer), data: Buffer.from(response.data as ArrayBuffer),
contentType: (response as { headers?: Record<string, string> }).headers?.["content-type"] ?? "application/octet-stream", contentType: headers?.["content-type"] ?? "application/octet-stream",
filename: match?.[1] ?? "document.pdf", filename: match?.[1] ?? "document.pdf",
}; };
} }