feat: implement API endpoint interceptor and update app configuration #5
This commit is contained in:
@@ -2,9 +2,10 @@ import { ApplicationConfig, inject, provideAppInitializer, provideBrowserGlobalE
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
import { HTTP_INTERCEPTORS, provideHttpClient } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||||
import { DefaultOAuthInterceptor, provideOAuthClient } from 'angular-oauth2-oidc';
|
import { DefaultOAuthInterceptor, provideOAuthClient } from 'angular-oauth2-oidc';
|
||||||
import { AppConfigService } from './services/config.service';
|
import { AppConfigService } from './services/config.service';
|
||||||
|
import { ApiEndpointInterceptor } from './services/http.interceptor';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
@@ -12,17 +13,22 @@ export const appConfig: ApplicationConfig = {
|
|||||||
provideZonelessChangeDetection(),
|
provideZonelessChangeDetection(),
|
||||||
provideRouter(routes),
|
provideRouter(routes),
|
||||||
provideAppInitializer(() => inject(AppConfigService).loadConfig()),
|
provideAppInitializer(() => inject(AppConfigService).loadConfig()),
|
||||||
provideHttpClient(),
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: DefaultOAuthInterceptor,
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: ApiEndpointInterceptor,
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
provideOAuthClient({
|
provideOAuthClient({
|
||||||
resourceServer: {
|
resourceServer: {
|
||||||
allowedUrls: ['http://localhost:5000', 'https://localhost:5001', 'https://centrum.lesko.me'],
|
allowedUrls: ['http://localhost:5000', 'https://localhost:5001', 'https://centrum.lesko.me'],
|
||||||
sendAccessToken: true,
|
sendAccessToken: true,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{
|
|
||||||
provide: HTTP_INTERCEPTORS,
|
|
||||||
useClass: DefaultOAuthInterceptor,
|
|
||||||
multi: true,
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export class App implements OnInit {
|
|||||||
clientId: '21131567-fea1-42a2-8907-21abd874eff8',
|
clientId: '21131567-fea1-42a2-8907-21abd874eff8',
|
||||||
scope: 'openid profile email',
|
scope: 'openid profile email',
|
||||||
responseType: 'code',
|
responseType: 'code',
|
||||||
showDebugInformation: true,
|
|
||||||
timeoutFactor: 0.01,
|
timeoutFactor: 0.01,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,8 @@ export class Content {
|
|||||||
data = signal({});
|
data = signal({});
|
||||||
|
|
||||||
constructor(httpClient: HttpClient, readonly as: OAuthService, readonly cs: AppConfigService) {
|
constructor(httpClient: HttpClient, readonly as: OAuthService, readonly cs: AppConfigService) {
|
||||||
httpClient.get((isDevMode() ? cs.setting.apiEndpoint : '') + '/api/product', {
|
httpClient.get('/api/product')
|
||||||
headers: new HttpHeaders({ Authorization: `Bearer ${as.getAccessToken()}` }).append('Content-Type', 'application/json')
|
.subscribe(data => {
|
||||||
}).subscribe(data => {
|
|
||||||
this.data.set(data);
|
this.data.set(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { Observable } from 'rxjs';
|
||||||
import { Observable, tap } from 'rxjs';
|
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AppConfigService {
|
export class AppConfigService {
|
||||||
private config: any;
|
private config: any;
|
||||||
|
|
||||||
constructor(private readonly http: HttpClient) { }
|
public loaded: boolean = false;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
loadConfig(): Observable<any> {
|
loadConfig(): Observable<any> {
|
||||||
return this.http.get('/config.json')
|
return new Observable(observer => {
|
||||||
.pipe(tap(data => this.config = data))
|
fetch('/config.json')
|
||||||
|
.then(async response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Could not load config.json: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
this.config = await response.json();
|
||||||
|
this.loaded = true;
|
||||||
|
observer.next(this.config);
|
||||||
|
observer.complete();
|
||||||
|
})
|
||||||
|
.catch(error => observer.error(error));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get setting() {
|
get setting() {
|
||||||
|
|||||||
25
Web/src/app/services/http.interceptor.ts
Normal file
25
Web/src/app/services/http.interceptor.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { AppConfigService } from './config.service';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class ApiEndpointInterceptor implements HttpInterceptor {
|
||||||
|
constructor(private readonly configService: AppConfigService) { }
|
||||||
|
|
||||||
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
return this.prependUrl(req, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
prependUrl(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
const apiEndpoint = this.configService.setting.apiEndpoint;
|
||||||
|
if (apiEndpoint === undefined || !this.configService.loaded)
|
||||||
|
throw new Error('API endpoint is not defined or config not loaded');
|
||||||
|
|
||||||
|
const isRelative = !/^https?:\/\//i.test(req.url);
|
||||||
|
const url = isRelative ? `${apiEndpoint.replace(/\/$/, '')}/${req.url.replace(/^\//, '')}` : req.url;
|
||||||
|
const cloned = req.clone({ url });
|
||||||
|
console.trace('ApiEndpointInterceptor hit:', url);
|
||||||
|
return next.handle(cloned);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user