Merge pull request #4078 from cryst-hq/codex/fix-umami-4062

Fix metadata base URL generation
This commit is contained in:
Mike Cao
2026-03-09 23:32:11 -07:00
committed by GitHub
3 changed files with 99 additions and 6 deletions
+11 -6
View File
@@ -43,9 +43,14 @@ export default function ({ children }) {
);
}
export const metadata: Metadata = {
title: {
template: '%s | Umami',
default: 'Umami',
},
};
export async function generateMetadata(): Promise<Metadata> {
const headerStore = await headers();
return {
metadataBase: getBaseUrl(headerStore),
title: {
template: '%s | Umami',
default: 'Umami',
},
};
}
+48
View File
@@ -0,0 +1,48 @@
import { HOMEPAGE_URL } from '../constants';
import { getBaseUrl } from '../get-base-url';
function createHeaders(entries: Record<string, string>) {
return {
get(name: string) {
return entries[name.toLowerCase()] ?? null;
},
};
}
test('prefers forwarded host and protocol', () => {
const url = getBaseUrl(
createHeaders({
'x-forwarded-host': 'umami.is',
'x-forwarded-proto': 'https',
host: 'localhost:3000',
}),
);
expect(url.toString()).toBe('https://umami.is/');
});
test('falls back to host header', () => {
const url = getBaseUrl(
createHeaders({
host: 'analytics.example.com',
}),
);
expect(url.toString()).toBe('https://analytics.example.com/');
});
test('uses http for localhost hosts', () => {
const url = getBaseUrl(
createHeaders({
host: 'localhost:3000',
}),
);
expect(url.toString()).toBe('http://localhost:3000/');
});
test('falls back to homepage when host is missing', () => {
const url = getBaseUrl(createHeaders({}));
expect(url.toString()).toBe(`${HOMEPAGE_URL}/`);
});
+40
View File
@@ -0,0 +1,40 @@
import { HOMEPAGE_URL } from './constants';
type HeaderStore = Pick<Headers, 'get'>;
function getFirstHeaderValue(value?: string | null) {
return value?.split(',')[0]?.trim();
}
function getDefaultProtocol(host?: string) {
if (!host) {
return 'https';
}
if (host.startsWith('localhost') || host.startsWith('127.0.0.1') || host.startsWith('[::1]')) {
return 'http';
}
return 'https';
}
export function getBaseUrl(headers?: HeaderStore) {
const host =
getFirstHeaderValue(headers?.get('x-forwarded-host')) ||
getFirstHeaderValue(headers?.get('host'));
if (!host) {
return new URL(HOMEPAGE_URL);
}
const protocol =
getFirstHeaderValue(headers?.get('x-forwarded-proto')) ||
getFirstHeaderValue(headers?.get('x-forwarded-protocol')) ||
getDefaultProtocol(host);
try {
return new URL(`${protocol}://${host}`);
} catch {
return new URL(HOMEPAGE_URL);
}
}