From dee473fe4630881eb2f689dbba713a0bb3c15413 Mon Sep 17 00:00:00 2001 From: Florian THIERRY Date: Thu, 26 Sep 2024 10:38:52 +0200 Subject: [PATCH] Add interceptor to inject correlation id in http requests. --- frontend/package-lock.json | 30 ++++++++++++++++--- frontend/package.json | 2 ++ frontend/src/app/app.config.ts | 2 ++ .../interceptor/correlation-id.interceptor.ts | 20 +++++++++++++ .../core/service/correlation-id.service.ts | 27 +++++++++++++++++ 5 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 frontend/src/app/core/interceptor/correlation-id.interceptor.ts create mode 100644 frontend/src/app/core/service/correlation-id.service.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1245893..e984f33 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -20,6 +20,7 @@ "@angular/router": "^18.2.5", "rxjs": "~7.8.0", "tslib": "^2.3.0", + "uuid": "^10.0.0", "zone.js": "~0.14.10" }, "devDependencies": { @@ -28,6 +29,7 @@ "@angular/compiler-cli": "^18.2.5", "@angular/localize": "^18.2.5", "@types/jasmine": "~5.1.0", + "@types/uuid": "^10.0.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", @@ -4655,6 +4657,13 @@ "@types/node": "*" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/wrap-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", @@ -12427,6 +12436,16 @@ "websocket-driver": "^0.7.4" } }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/socks": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", @@ -13315,10 +13334,13 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", "bin": { "uuid": "dist/bin/uuid" diff --git a/frontend/package.json b/frontend/package.json index b91a572..fae9f68 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -29,6 +29,7 @@ "@angular/router": "^18.2.5", "rxjs": "~7.8.0", "tslib": "^2.3.0", + "uuid": "^10.0.0", "zone.js": "~0.14.10" }, "devDependencies": { @@ -37,6 +38,7 @@ "@angular/compiler-cli": "^18.2.5", "@angular/localize": "^18.2.5", "@types/jasmine": "~5.1.0", + "@types/uuid": "^10.0.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", diff --git a/frontend/src/app/app.config.ts b/frontend/src/app/app.config.ts index 58985bc..018d468 100644 --- a/frontend/src/app/app.config.ts +++ b/frontend/src/app/app.config.ts @@ -5,6 +5,7 @@ import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@a import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { routes } from './app.routes'; import { JwtInterceptor } from './core/interceptor/jwt.interceptor'; +import { CorrelationIdInterceptor } from './core/interceptor/correlation-id.interceptor'; export const appConfig: ApplicationConfig = { providers: [ @@ -18,5 +19,6 @@ export const appConfig: ApplicationConfig = { provideAnimationsAsync(), provideHttpClient(withInterceptorsFromDi()), { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: CorrelationIdInterceptor, multi: true }, ] }; diff --git a/frontend/src/app/core/interceptor/correlation-id.interceptor.ts b/frontend/src/app/core/interceptor/correlation-id.interceptor.ts new file mode 100644 index 0000000..e079beb --- /dev/null +++ b/frontend/src/app/core/interceptor/correlation-id.interceptor.ts @@ -0,0 +1,20 @@ +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http"; +import { inject, Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { CorrelationIdService } from "../service/correlation-id.service"; + +@Injectable() +export class CorrelationIdInterceptor implements HttpInterceptor { + private readonly correlationIdService = inject(CorrelationIdService); + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + const correlationId = this.correlationIdService.getCorrelationId(); + + const requestWithCorrelationId = request.clone({ + headers: request.headers.set('x-correlation-id', correlationId) + }); + + return next.handle(requestWithCorrelationId); + } + +} \ No newline at end of file diff --git a/frontend/src/app/core/service/correlation-id.service.ts b/frontend/src/app/core/service/correlation-id.service.ts new file mode 100644 index 0000000..ed06436 --- /dev/null +++ b/frontend/src/app/core/service/correlation-id.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from "@angular/core"; +import * as uuid from 'uuid'; + +const CORRELATION_ID_KEY = 'correlationId'; + +@Injectable({ + providedIn: 'root' +}) +export class CorrelationIdService { + getCorrelationId(): string { + let correlationId = this.getCorrelationFromLocalStorage(); + if (correlationId === undefined) { + correlationId = this.createNewCorrelationId(); + } + return correlationId; + } + + private getCorrelationFromLocalStorage(): string | undefined { + return localStorage.getItem(CORRELATION_ID_KEY) ?? undefined; + } + + private createNewCorrelationId(): string { + const newCorrelationId = uuid.v4(); + localStorage.setItem(CORRELATION_ID_KEY, newCorrelationId); + return newCorrelationId; + } +} \ No newline at end of file