fix: keep the server's path prefix in the CalDAV addresses shown in calendar settings

This commit is contained in:
Linus Rath
2026-10-26 14:52:04 +01:00
parent f8c429f217
commit 885ecdaa07
2 changed files with 11 additions and 1 deletions
+2 -1
View File
@@ -18,8 +18,9 @@ interface DiscoveryResult {
const MAX_ACCOUNTS = 10;
const MAX_CANDIDATES_PER_ACCOUNT = 10;
/** Appends to the server address, keeping a path prefix (Stalwart behind https://host/stalwart), like /api/webdav. */
function buildPublicUrl(serverUrl: string, path: string): string {
return new URL(path, serverUrl).toString();
return new URL(`${serverUrl.replace(/\/+$/, '')}${path}`).toString();
}
async function probeCalendarHome(
@@ -86,6 +86,15 @@ describe('POST /api/caldav/discover', () => {
expect((await res.json()).accounts.A).toEqual({ url: target('c2'), resolvedAccount: 'c2' });
});
it('keeps the path prefix of a server mounted below the root', async () => {
mockCreds.mockResolvedValue({ ...CREDS, serverUrl: 'https://host.example.com/stalwart/' });
fetchSpy.mockResolvedValue({ status: 207, headers: new Headers() });
const data = await read(await POST(makeReq({ accounts: [{ key: 'A', candidates: ['c1'] }] }))).json();
expect(data.wellKnownUrl).toBe('https://host.example.com/stalwart/.well-known/caldav');
expect(data.accounts.A.url).toBe('https://host.example.com/stalwart/dav/cal/c1');
expect(fetchSpy).toHaveBeenCalledWith('https://host.example.com/stalwart/dav/cal/c1', expect.anything());
});
it('de-duplicates and trims candidates before probing', async () => {
fetchSpy.mockResolvedValue({ status: 404, headers: new Headers() });
await POST(makeReq({ accounts: [{ key: 'A', candidates: [' c1 ', 'c1', '', 'c1'] }] }));