The application is published at horaires.ita-ito.com. One origin serves both the panel and the browser, so the OIDC callback, the image URL the device is handed and the documentation all follow from this single name. Port 3000 is already taken by the facture_ocr stack on the development machine, so the app listens on 3010 there and the reason is written next to the setting rather than left to be rediscovered. The fixtures and the frozen payload snapshot move to the real domain too: a contract snapshot carrying a hostname that never existed is a small puzzle left for whoever reads it next. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012cSY9pVhZmJUKNN7wf1Myd
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
/**
|
|
* Environment access, in one place so nothing else has to guess.
|
|
*/
|
|
|
|
/**
|
|
* The origin the device and the browser reach us on.
|
|
*
|
|
* Prefers what the request actually arrived as, because the panel has to be
|
|
* handed a URL it can fetch — a mismatch here shows up as a blank screen in a
|
|
* shop window, which is the most expensive place to debug. Falls back to the
|
|
* configured domain for calls that have no request, such as background jobs.
|
|
*/
|
|
export function publicBaseUrl(request?: Request): string {
|
|
if (request) {
|
|
const host = request.headers.get('x-forwarded-host') ?? request.headers.get('host');
|
|
if (host) {
|
|
const proto = request.headers.get('x-forwarded-proto') ?? new URL(request.url).protocol.replace(':', '');
|
|
return `${proto}://${host}`;
|
|
}
|
|
}
|
|
|
|
const configured = process.env.NEXTAUTH_URL;
|
|
if (configured) {
|
|
return configured.replace(/\/$/, '');
|
|
}
|
|
|
|
const domain = process.env.APP_DOMAIN;
|
|
if (domain) {
|
|
return domain.startsWith('http') ? domain.replace(/\/$/, '') : `https://${domain}`;
|
|
}
|
|
|
|
return 'http://localhost:3010';
|
|
}
|
|
|
|
/**
|
|
* Whether the panel may talk to us over plain HTTP.
|
|
*
|
|
* Off by default. It exists because these ESP32 firmwares sometimes fail on a
|
|
* certificate chain, and a shop with a blank window needs a way out that does
|
|
* not involve reflashing. The device token is separate and revocable precisely
|
|
* so this switch stays survivable.
|
|
*/
|
|
export function deviceAllowsHttp(): boolean {
|
|
return process.env.DEVICE_ALLOW_HTTP === 'true';
|
|
}
|