Chore: Http interceptors refactor (#11923)

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
Pierre Nédélec
2026-01-28 16:18:48 +01:00
committed by GitHub
parent 01b21377af
commit 4cbe56e3af
5 changed files with 97 additions and 86 deletions

View File

@@ -1,30 +1,41 @@
import { HttpEvent, HttpRequest } from '@angular/common/http'
import {
HttpClient,
provideHttpClient,
withInterceptors,
} from '@angular/common/http'
import {
HttpTestingController,
provideHttpClientTesting,
} from '@angular/common/http/testing'
import { TestBed } from '@angular/core/testing'
import { of } from 'rxjs'
import { environment } from 'src/environments/environment'
import { ApiVersionInterceptor } from './api-version.interceptor'
import { withApiVersionInterceptor } from './api-version.interceptor'
describe('ApiVersionInterceptor', () => {
let interceptor: ApiVersionInterceptor
let httpClient: HttpClient
let httpMock: HttpTestingController
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ApiVersionInterceptor],
providers: [
provideHttpClient(withInterceptors([withApiVersionInterceptor])),
provideHttpClientTesting(),
],
})
interceptor = TestBed.inject(ApiVersionInterceptor)
httpClient = TestBed.inject(HttpClient)
httpMock = TestBed.inject(HttpTestingController)
})
it('should add api version to headers', () => {
interceptor.intercept(new HttpRequest('GET', 'https://example.com'), {
handle: (request) => {
const header = request.headers['lazyUpdate'][0]
expect(header.name).toEqual('Accept')
expect(header.value).toEqual(
`application/json; version=${environment.apiVersion}`
)
return of({} as HttpEvent<any>)
},
})
httpClient.get('https://example.com').subscribe()
const request = httpMock.expectOne('https://example.com')
const header = request.request.headers['lazyUpdate'][0]
expect(header.name).toEqual('Accept')
expect(header.value).toEqual(
`application/json; version=${environment.apiVersion}`
)
request.flush({})
})
})

View File

@@ -1,27 +1,20 @@
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpHandlerFn,
HttpInterceptorFn,
HttpRequest,
} from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
@Injectable()
export class ApiVersionInterceptor implements HttpInterceptor {
constructor() {}
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
request = request.clone({
setHeaders: {
Accept: `application/json; version=${environment.apiVersion}`,
},
})
return next.handle(request)
}
export const withApiVersionInterceptor: HttpInterceptorFn = (
request: HttpRequest<unknown>,
next: HttpHandlerFn
): Observable<HttpEvent<unknown>> => {
request = request.clone({
setHeaders: {
Accept: `application/json; version=${environment.apiVersion}`,
},
})
return next(request)
}

View File

@@ -1,35 +1,52 @@
import { HttpEvent, HttpRequest } from '@angular/common/http'
import {
HttpClient,
provideHttpClient,
withInterceptors,
} from '@angular/common/http'
import {
HttpTestingController,
provideHttpClientTesting,
} from '@angular/common/http/testing'
import { TestBed } from '@angular/core/testing'
import { Meta } from '@angular/platform-browser'
import { CookieService } from 'ngx-cookie-service'
import { of } from 'rxjs'
import { CsrfInterceptor } from './csrf.interceptor'
import { withCsrfInterceptor } from './csrf.interceptor'
describe('CsrfInterceptor', () => {
let interceptor: CsrfInterceptor
let meta: Meta
let cookieService: CookieService
let httpClient: HttpClient
let httpMock: HttpTestingController
beforeEach(() => {
TestBed.configureTestingModule({
providers: [CsrfInterceptor, Meta, CookieService],
providers: [
Meta,
CookieService,
provideHttpClient(withInterceptors([withCsrfInterceptor])),
provideHttpClientTesting(),
],
})
meta = TestBed.inject(Meta)
cookieService = TestBed.inject(CookieService)
interceptor = TestBed.inject(CsrfInterceptor)
httpClient = TestBed.inject(HttpClient)
httpMock = TestBed.inject(HttpTestingController)
})
it('should get csrf token', () => {
meta.addTag({ name: 'cookie_prefix', content: 'ngx-' }, true)
const cookieServiceSpy = jest.spyOn(cookieService, 'get')
cookieServiceSpy.mockReturnValue('csrftoken')
interceptor.intercept(new HttpRequest('GET', 'https://example.com'), {
handle: (request) => {
expect(request.headers['lazyUpdate'][0]['name']).toEqual('X-CSRFToken')
return of({} as HttpEvent<any>)
},
})
httpClient.get('https://example.com').subscribe()
const request = httpMock.expectOne('https://example.com')
expect(request.request.headers['lazyUpdate'][0]['name']).toEqual(
'X-CSRFToken'
)
expect(cookieServiceSpy).toHaveBeenCalled()
request.flush({})
})
})

View File

@@ -1,36 +1,32 @@
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpHandlerFn,
HttpInterceptorFn,
HttpRequest,
} from '@angular/common/http'
import { inject, Injectable } from '@angular/core'
import { inject } from '@angular/core'
import { Meta } from '@angular/platform-browser'
import { CookieService } from 'ngx-cookie-service'
import { Observable } from 'rxjs'
@Injectable()
export class CsrfInterceptor implements HttpInterceptor {
private cookieService: CookieService = inject(CookieService)
private meta: Meta = inject(Meta)
export const withCsrfInterceptor: HttpInterceptorFn = (
request: HttpRequest<unknown>,
next: HttpHandlerFn
): Observable<HttpEvent<unknown>> => {
const cookieService: CookieService = inject(CookieService)
const meta: Meta = inject(Meta)
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
let prefix = ''
if (this.meta.getTag('name=cookie_prefix')) {
prefix = this.meta.getTag('name=cookie_prefix').content
}
let csrfToken = this.cookieService.get(`${prefix}csrftoken`)
if (csrfToken) {
request = request.clone({
setHeaders: {
'X-CSRFToken': csrfToken,
},
})
}
return next.handle(request)
let prefix = ''
if (meta.getTag('name=cookie_prefix')) {
prefix = meta.getTag('name=cookie_prefix').content
}
let csrfToken = cookieService.get(`${prefix}csrftoken`)
if (csrfToken) {
request = request.clone({
setHeaders: {
'X-CSRFToken': csrfToken,
},
})
}
return next(request)
}