Angular HttpClient et Interceptors en 2026 : Gestion des Requêtes et Questions d'Entretien
Guide complet sur HttpClient et les interceptors Angular en 2026. Architecture des requêtes HTTP, gestion des erreurs, authentification et questions d'entretien technique.

Angular reste en 2026 l'un des frameworks frontend les plus utilisés en entreprise, et la maîtrise de HttpClient constitue une compétence essentielle pour tout développeur Angular. Ce guide explore en profondeur le fonctionnement de HttpClient, l'architecture des interceptors fonctionnels, et les questions fréquemment posées en entretien technique.
Depuis Angular 15, les interceptors fonctionnels remplacent progressivement les interceptors basés sur des classes. Ce guide couvre les deux approches, avec un focus sur les patterns modernes recommandés en 2026.
Configuration de HttpClient dans Angular 19
La configuration de HttpClient a considérablement évolué avec l'adoption des standalone components. La méthode moderne utilise provideHttpClient() dans la configuration de l'application.
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors, withFetch } from '@angular/common/http';
import { authInterceptor } from './interceptors/auth.interceptor';
import { errorInterceptor } from './interceptors/error.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withInterceptors([authInterceptor, errorInterceptor]),
withFetch() // Uses fetch API instead of XMLHttpRequest
)
]
};L'option withFetch() permet d'utiliser l'API Fetch native du navigateur plutôt que XMLHttpRequest, offrant de meilleures performances et une meilleure intégration avec les Service Workers.
Création d'un Service HTTP Typé
Un service HTTP bien structuré constitue la base d'une architecture Angular robuste. L'utilisation de génériques TypeScript garantit la sécurité des types à travers toute l'application.
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../environments/environment';
export interface ApiResponse<T> {
data: T;
message: string;
status: number;
}
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
pageSize: number;
}
@Injectable({ providedIn: 'root' })
export class ApiService {
private http = inject(HttpClient);
private baseUrl = environment.apiUrl;
get<T>(endpoint: string, params?: Record<string, string>): Observable<ApiResponse<T>> {
const httpParams = new HttpParams({ fromObject: params || {} });
return this.http.get<ApiResponse<T>>(`${this.baseUrl}${endpoint}`, { params: httpParams });
}
post<T, R>(endpoint: string, body: T): Observable<ApiResponse<R>> {
return this.http.post<ApiResponse<R>>(`${this.baseUrl}${endpoint}`, body);
}
put<T, R>(endpoint: string, body: T): Observable<ApiResponse<R>> {
return this.http.put<ApiResponse<R>>(`${this.baseUrl}${endpoint}`, body);
}
delete<T>(endpoint: string): Observable<ApiResponse<T>> {
return this.http.delete<ApiResponse<T>>(`${this.baseUrl}${endpoint}`);
}
uploadFile(endpoint: string, file: File): Observable<ApiResponse<{ url: string }>> {
const formData = new FormData();
formData.append('file', file);
return this.http.post<ApiResponse<{ url: string }>>(`${this.baseUrl}${endpoint}`, formData);
}
}Interceptors Fonctionnels : L'Approche Moderne
Les interceptors fonctionnels introduits dans Angular 15 offrent une syntaxe plus concise et une meilleure composabilité. Ils s'intègrent parfaitement avec l'architecture standalone.
Interceptor d'Authentification
L'ajout automatique du token d'authentification représente le cas d'usage le plus courant des interceptors.
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { AuthService } from '../services/auth.service';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const authService = inject(AuthService);
const token = authService.getAccessToken();
if (token && !req.url.includes('/auth/')) {
const clonedRequest = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next(clonedRequest);
}
return next(req);
};Interceptor de Gestion des Erreurs
Un interceptor centralisé pour la gestion des erreurs simplifie considérablement le code des composants.
import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { catchError, throwError } from 'rxjs';
import { NotificationService } from '../services/notification.service';
export const errorInterceptor: HttpInterceptorFn = (req, next) => {
const router = inject(Router);
const notifications = inject(NotificationService);
return next(req).pipe(
catchError((error: HttpErrorResponse) => {
switch (error.status) {
case 401:
router.navigate(['/login']);
break;
case 403:
notifications.error('Access denied');
break;
case 404:
notifications.error('Resource not found');
break;
case 500:
notifications.error('Server error. Please try again later.');
break;
default:
notifications.error(error.message || 'An error occurred');
}
return throwError(() => error);
})
);
};Interceptor de Retry avec Backoff Exponentiel
La gestion des échecs réseau transitoires nécessite une stratégie de retry intelligente.
import { HttpInterceptorFn } from '@angular/common/http';
import { retry, timer } from 'rxjs';
export const retryInterceptor: HttpInterceptorFn = (req, next) => {
const maxRetries = 3;
const delayMs = 1000;
return next(req).pipe(
retry({
count: maxRetries,
delay: (error, retryCount) => {
if (error.status >= 400 && error.status < 500) {
throw error; // Don't retry client errors
}
const backoffDelay = delayMs * Math.pow(2, retryCount - 1);
console.log(`Retry attempt ${retryCount} after ${backoffDelay}ms`);
return timer(backoffDelay);
}
})
);
};Gestion du Cache avec Interceptors
L'implémentation d'un cache HTTP au niveau de l'interceptor permet d'optimiser les performances sans modifier les services existants.
import { HttpInterceptorFn, HttpResponse } from '@angular/common/http';
import { of, tap } from 'rxjs';
const cache = new Map<string, { response: HttpResponse<unknown>; timestamp: number }>();
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
if (req.method !== 'GET') {
return next(req);
}
const cacheKey = req.urlWithParams;
const cached = cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
return of(cached.response.clone());
}
return next(req).pipe(
tap((event) => {
if (event instanceof HttpResponse) {
cache.set(cacheKey, { response: event.clone(), timestamp: Date.now() });
}
})
);
};Interceptor de Loading Global
L'affichage automatique d'un indicateur de chargement améliore l'expérience utilisateur.
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { finalize } from 'rxjs';
import { LoadingService } from '../services/loading.service';
export const loadingInterceptor: HttpInterceptorFn = (req, next) => {
const loadingService = inject(LoadingService);
if (req.headers.has('X-Skip-Loading')) {
return next(req);
}
loadingService.show();
return next(req).pipe(
finalize(() => loadingService.hide())
);
};Patterns Avancés : Refresh Token Automatique
La gestion automatique du refresh token représente un pattern essentiel pour les applications sécurisées.
import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
import { inject } from '@angular/core';
import { BehaviorSubject, throwError } from 'rxjs';
import { catchError, filter, switchMap, take } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
let isRefreshing = false;
const refreshTokenSubject = new BehaviorSubject<string | null>(null);
export const tokenRefreshInterceptor: HttpInterceptorFn = (req, next) => {
const authService = inject(AuthService);
return next(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status !== 401 || req.url.includes('/auth/refresh')) {
return throwError(() => error);
}
if (isRefreshing) {
return refreshTokenSubject.pipe(
filter((token) => token !== null),
take(1),
switchMap((token) => {
const cloned = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return next(cloned);
})
);
}
isRefreshing = true;
refreshTokenSubject.next(null);
return authService.refreshToken().pipe(
switchMap((response) => {
isRefreshing = false;
refreshTokenSubject.next(response.accessToken);
const cloned = req.clone({
setHeaders: { Authorization: `Bearer ${response.accessToken}` }
});
return next(cloned);
}),
catchError((refreshError) => {
isRefreshing = false;
authService.logout();
return throwError(() => refreshError);
})
);
})
);
};Prêt à réussir tes entretiens Angular ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Questions d'Entretien Fréquentes
Les questions suivantes apparaissent régulièrement lors d'entretiens techniques Angular.
Quelle est la différence entre HttpClient et l'API Fetch native ?
HttpClient offre plusieurs avantages par rapport à l'API Fetch : intégration native avec RxJS, système d'interceptors, typage fort avec TypeScript, et gestion automatique de la sérialisation JSON. L'API Fetch reste plus légère mais nécessite plus de code boilerplate.
Comment fonctionne l'ordre d'exécution des interceptors ?
Les interceptors s'exécutent dans l'ordre de leur déclaration pour les requêtes sortantes, et dans l'ordre inverse pour les réponses entrantes. Cette architecture en "oignon" permet de chaîner les transformations de manière prévisible.
Comment annuler une requête HTTP en cours ?
L'annulation s'effectue via la désinscription à l'Observable retourné par HttpClient. L'utilisation de l'opérateur takeUntil avec un Subject permet de gérer proprement l'annulation lors de la destruction d'un composant.
// Example: Cancelling requests on component destroy
import { Component, OnDestroy } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
@Component({ /* ... */ })
export class SearchComponent implements OnDestroy {
private destroy$ = new Subject<void>();
search(term: string) {
this.apiService.search(term)
.pipe(takeUntil(this.destroy$))
.subscribe(results => this.results = results);
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}Quand utiliser HttpParams vs un objet simple ?
HttpParams garantit l'encodage correct des paramètres URL et supporte les valeurs multiples pour une même clé. Un objet simple convient pour les cas simples, mais HttpParams reste recommandé pour les requêtes complexes.
Comment tester un service utilisant HttpClient ?
Angular fournit HttpTestingController pour simuler les requêtes HTTP dans les tests unitaires. Cette approche permet de vérifier les URLs appelées, les headers envoyés, et de simuler différentes réponses.
// Example: Testing HTTP service
import { TestBed } from '@angular/core/testing';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';
describe('ApiService', () => {
let service: ApiService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
provideHttpClient(),
provideHttpClientTesting()
]
});
service = TestBed.inject(ApiService);
httpMock = TestBed.inject(HttpTestingController);
});
it('should fetch users', () => {
const mockUsers = [{ id: 1, name: 'John' }];
service.get<User[]>('/users').subscribe(response => {
expect(response.data).toEqual(mockUsers);
});
const req = httpMock.expectOne('/api/users');
expect(req.request.method).toBe('GET');
req.flush({ data: mockUsers, message: 'OK', status: 200 });
});
afterEach(() => {
httpMock.verify();
});
});Bonnes Pratiques en 2026
Plusieurs recommandations émergent pour une utilisation optimale de HttpClient en production.
La centralisation des appels HTTP dans des services dédiés facilite la maintenance et les tests. L'utilisation systématique des interceptors pour les préoccupations transversales (authentification, logging, cache) évite la duplication de code.
Le typage strict de toutes les réponses API avec des interfaces TypeScript permet de détecter les erreurs à la compilation. L'adoption des interceptors fonctionnels simplifie la configuration et améliore les performances grâce au tree-shaking.
La gestion explicite des erreurs à chaque niveau (interceptor global pour les erreurs communes, gestion spécifique dans les composants pour les cas particuliers) garantit une expérience utilisateur cohérente.
Conclusion
HttpClient et les interceptors constituent le socle de la communication HTTP dans les applications Angular. La maîtrise de ces concepts, des patterns de base aux techniques avancées comme le refresh token automatique, représente une compétence clé évaluée lors des entretiens techniques. L'adoption des interceptors fonctionnels et des bonnes pratiques présentées dans ce guide permet de construire des applications robustes et maintenables.
Tu saurais repérer le bug en Angular ?
Un vrai bout de code, un bug caché, une tentative par jour. Sans compte pour essayer.

Écrit par
Anthony Fillion-MailletFondateur de SharpSkill
Développeur fullstack depuis plus de 10 ans. Il dirige SharpSkill et répond de tout ce qui y est publié.
Mis à jour le 22 août 2026
Tags
Partager
Articles similaires

Injection de Dépendances Angular Avancée en 2026 : Providers, Tokens et Questions d'Entretien
Maîtriser l'injection de dépendances Angular avec InjectionToken, les injecteurs hiérarchiques, les modificateurs de résolution et les multi-providers. Inclut des questions d'entretien et des patterns de production.

RxJS dans Angular 2026 : operators, Subjects et interop Signals
RxJS dans Angular 2026 : maîtriser les operators, les Subjects et les patterns d'interop Signals utilisés en production, ainsi que les questions d'entretien les plus fréquentes.

Angular 20 en 2026 : Resource API, httpResource et questions d'entretien
Angular 20 introduit httpResource et stabilise la Resource API pour la récupération de données fondée sur les signals. Un tutoriel pratique sur resource(), rxResource(), httpResource(), la validation Zod et les questions d'entretien courantes.