dev #42
@@ -17,6 +17,11 @@ import {
|
|||||||
TranslateHttpLoader,
|
TranslateHttpLoader,
|
||||||
} from '@ngx-translate/http-loader';
|
} from '@ngx-translate/http-loader';
|
||||||
import { adminAuthInterceptor } from './core/interceptors/admin-auth.interceptor';
|
import { adminAuthInterceptor } from './core/interceptors/admin-auth.interceptor';
|
||||||
|
import {
|
||||||
|
provideClientHydration,
|
||||||
|
withEventReplay,
|
||||||
|
} from '@angular/platform-browser';
|
||||||
|
import { serverOriginInterceptor } from './core/interceptors/server-origin.interceptor';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
@@ -29,7 +34,9 @@ export const appConfig: ApplicationConfig = {
|
|||||||
scrollPositionRestoration: 'top',
|
scrollPositionRestoration: 'top',
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
provideHttpClient(withInterceptors([adminAuthInterceptor])),
|
provideHttpClient(
|
||||||
|
withInterceptors([serverOriginInterceptor, adminAuthInterceptor]),
|
||||||
|
),
|
||||||
provideTranslateHttpLoader({
|
provideTranslateHttpLoader({
|
||||||
prefix: './assets/i18n/',
|
prefix: './assets/i18n/',
|
||||||
suffix: '.json',
|
suffix: '.json',
|
||||||
@@ -43,5 +50,6 @@ export const appConfig: ApplicationConfig = {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
provideClientHydration(withEventReplay()),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { HttpInterceptorFn } from '@angular/common/http';
|
||||||
|
import { inject, REQUEST } from '@angular/core';
|
||||||
|
|
||||||
|
type RequestLike = {
|
||||||
|
protocol?: string;
|
||||||
|
get?: (name: string) => string | undefined;
|
||||||
|
headers?: Record<string, string | string[] | undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isAbsoluteUrl(url: string): boolean {
|
||||||
|
return /^[a-z][a-z\d+\-.]*:/i.test(url) || url.startsWith('//');
|
||||||
|
}
|
||||||
|
|
||||||
|
function firstHeaderValue(
|
||||||
|
value: string | string[] | undefined,
|
||||||
|
): string | null {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value[0] ?? null;
|
||||||
|
}
|
||||||
|
return typeof value === 'string' ? value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveOrigin(request: RequestLike | null): string | null {
|
||||||
|
if (!request) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const host =
|
||||||
|
request.get?.('host') ??
|
||||||
|
firstHeaderValue(request.headers?.['host']) ??
|
||||||
|
firstHeaderValue(request.headers?.['x-forwarded-host']);
|
||||||
|
if (!host) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const forwardedProtoRaw = firstHeaderValue(
|
||||||
|
request.headers?.['x-forwarded-proto'],
|
||||||
|
);
|
||||||
|
const forwardedProto = forwardedProtoRaw
|
||||||
|
?.split(',')
|
||||||
|
.map((part) => part.trim().toLowerCase())
|
||||||
|
.find(Boolean);
|
||||||
|
const protocol = forwardedProto || request.protocol || 'http';
|
||||||
|
return `${protocol}://${host}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRelativePath(url: string): string {
|
||||||
|
const withoutDot = url.replace(/^\.\//, '');
|
||||||
|
return withoutDot.startsWith('/') ? withoutDot : `/${withoutDot}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const serverOriginInterceptor: HttpInterceptorFn = (req, next) => {
|
||||||
|
if (isAbsoluteUrl(req.url)) {
|
||||||
|
return next(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = inject(REQUEST, { optional: true }) as RequestLike | null;
|
||||||
|
const origin = resolveOrigin(request);
|
||||||
|
if (!origin) {
|
||||||
|
return next(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
const absoluteUrl = `${origin}${normalizeRelativePath(req.url)}`;
|
||||||
|
return next(req.clone({ url: absoluteUrl }));
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user