fix: prefix remaining <img>, favicon, and WebDAV URLs with basePath #319

This commit is contained in:
Linus Rath
2026-05-25 16:45:13 +02:00
parent 42ec34be21
commit e2abc8dee9
12 changed files with 49 additions and 22 deletions
+20
View File
@@ -75,6 +75,26 @@ export function apiFetch(input: string, init?: RequestInit): Promise<Response> {
return fetch(input, init);
}
/**
* Mount-prefix-aware wrapper for URL strings used in `<img src>`, `<link href>`,
* `window.location.*`, etc. — anything the browser resolves itself, where
* `apiFetch` can't help.
*
* Idempotent: passing an already-prefixed value, an external URL, a
* protocol-relative URL, or an empty/falsy value returns it unchanged. So it's
* safe to wrap admin-configurable values that might be either a local path
* (`/branding/foo.svg`, `/api/admin/branding/...`) or a full URL.
*/
export function withBasePath(url: string | null | undefined): string {
if (!url) return url ?? '';
if (url.charCodeAt(0) !== 47) return url; // not absolute (e.g. https://, data:, blob:)
if (url.charCodeAt(1) === 47) return url; // protocol-relative //cdn...
const prefix = getPathPrefix();
if (!prefix) return url;
if (url === prefix || url.startsWith(prefix + '/')) return url;
return prefix + url;
}
/**
* Extracts the locale from the current URL, skipping any mount prefix.
+3 -2
View File
@@ -4,6 +4,7 @@
*/
import { getActiveAccountSlotHeaders } from '@/lib/auth/active-account-slot';
import { apiFetch, withBasePath } from '@/lib/browser-navigation';
export interface WebDAVResource {
href: string;
@@ -32,7 +33,7 @@ export class WebDAVClient {
...options?.headers,
};
return fetch(this.proxyUrl, {
return apiFetch(this.proxyUrl, {
method: 'POST',
headers,
body: options?.body,
@@ -118,7 +119,7 @@ export class WebDAVClient {
// Use XMLHttpRequest for progress tracking
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', this.proxyUrl);
xhr.open('POST', withBasePath(this.proxyUrl));
xhr.setRequestHeader('X-WebDAV-Method', 'PUT');
xhr.setRequestHeader('X-WebDAV-Path', path);
const slotHeaders = getActiveAccountSlotHeaders();