fix: rewrite JMAP session URLs to match user-configured server origin

Fixes Docker/reverse proxy deployments where the JMAP server returns
its internal hostname in session URLs, causing all requests after
login to fail.
This commit is contained in:
Matthieu MALVACHE
2026-02-24 15:17:49 +01:00
committed by Matthieu MALVACHE
parent 913f673f73
commit ff3ae80f23
2 changed files with 25 additions and 0 deletions
+1
View File
@@ -23,6 +23,7 @@ This document tracks the development status and planned features for JMAP Webmai
- [x] Session establishment and keep-alive
- [x] Connection error handling and retries
- [x] CORS error detection with actionable user guidance
- [x] Session URL origin rewriting (fixes Docker/reverse proxy deployments where server returns internal hostname)
- [x] Storage quota display
- [x] Server capability detection
- [x] Shared folders support (multi-account access)
+24
View File
@@ -102,6 +102,8 @@ export class JMAPClient {
const session = await sessionResponse.json();
this.rewriteSessionUrls(session);
// Store the full session for reference
this.session = session;
@@ -208,6 +210,28 @@ export class JMAPClient {
this.capabilities = {};
}
private rewriteSessionUrl(url: string): string {
try {
const urlOrigin = new URL(url).origin;
const serverOrigin = new URL(this.serverUrl).origin;
if (urlOrigin === serverOrigin) return url;
return serverOrigin + url.slice(urlOrigin.length);
} catch {
return url;
}
}
private rewriteSessionUrls(session: JMAPSession): void {
session.apiUrl = this.rewriteSessionUrl(session.apiUrl);
session.downloadUrl = this.rewriteSessionUrl(session.downloadUrl);
if (session.uploadUrl) {
session.uploadUrl = this.rewriteSessionUrl(session.uploadUrl);
}
if (session.eventSourceUrl) {
session.eventSourceUrl = this.rewriteSessionUrl(session.eventSourceUrl);
}
}
private async request(methodCalls: JMAPMethodCall[], using?: string[]): Promise<JMAPResponse> {
if (!this.apiUrl) {
throw new Error('Not connected. Call connect() first.');