All topics
Servicesintermediate

Functional HTTP Interceptors

Explain the modern functional HttpInterceptorFn API and how it differs from class-based interceptors.

Angular 15 introduced functional interceptors as a lighter-weight alternative to the class-based HttpInterceptor interface, and by Angular 17+ they're the officially recommended approach for new code — a plain function matching the HttpInterceptorFn signature, registered via withInterceptors() inside provideHttpClient(), with no class, no @Injectable(), and no multi-provider token boilerplate required.

It's like replacing a formal permission slip and sign-off process (class-based interceptor registration) with a sticky note handed directly to the next person in line — same information passed along, far less paperwork.

Key Concepts

1
The functional form is (req, next) => { ... }, mirroring the same request/next-handler shape as the class-based version's intercept method, but as a standalone function that can use inject() internally to grab any services it needs (like an AuthService to read the current token), rather than receiving dependencies through a constructor.
(req, next) => { ... }interceptinject()AuthService
2
This change reflects Angular's broader move toward standalone, function-based APIs (mirroring input()/output() signals, functional route guards, etc.) that reduce ceremony and are easier to tree-shake and test in isolation, since a plain function is simpler to unit test than a class requiring TestBed setup.
input()output()TestBed
3
Interviewers often ask which one to use in new code: functional interceptors are the modern default recommendation, but understanding class-based interceptors is still necessary since large existing codebases and many third-party library examples still use them, and both can coexist in the same application during a migration.