fix(jmap): rewrite session URLs to match user-configured server origin

JMAP servers (e.g. Stalwart behind Docker) may return internal hostnames
in their session response (https://jmap/ instead of the actual server URL).
Replace the origin of all session URLs (apiUrl, downloadUrl, uploadUrl,
eventSourceUrl) with the user-configured server origin, using string
slicing to preserve RFC 6570 template placeholders without encoding.

Fixes #16
This commit is contained in:
Matthieu MALVACHE
2026-02-24 15:17:03 +01:00
parent 403eb565c9
commit 97ffb72d04
+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.');