Extend http interceptors in child module injector
See original GitHub issueš feature request
Relevant Package
This feature request is for @angular/common/http
Description
Ability to extend http interceptors in child module injectors since it is fairly simple, but the api to achieve it is āprivateā in angular.
Describe the solution youād like
Iāve already managed to do this by providing HttpHandler
, HttpClient
and HTTP_INTERCEPTORS
manually in the lazy loaded module without importing HttpClientModule
, since this module imports HttpClientXsrfModule
which provides a fresh HTTP_INTERCEPTORS
array, for the sake of reincluding HttpXsrfInterceptor
(imho, but why again?).
If this explanation was hard to follow, hereās the code
@NgModule({
providers: [{
provide: HttpClient,
useClass: HttpClient
}, {
provide: HttpHandler,
useClass: ɵHttpInterceptingHandler
}, {
provide: HTTP_INTERCEPTORS,
deps: [Injector],
useFactory: injector => [
...ARRAY_OF_CHILDREN_INTERCEPTOR,
...injector.parent.get(HTTP_INTERCEPTORS)
]
}]
})
export class FeatureModule {}
Here the āprivateā angular api is the class ɵHttpInterceptingHandler
and the injector.parent
part.
So, I think the most practical solution would be to maybe have an alternative HttpClientModule
that does not import HttpClientXsrfModule
so the interceptors array is not reset.
Or similarly, have both these modules without providers and have .forRoot(): ModuleWithProviders
options for each, of which HttpClientModule.forRoot()
would spread HttpClientXsrfModule.forRoot()
's providers.
Code again, if explanation was convoluted
class HttpClientModule {
static forRoot(): ModuleWithProviders<HttpClientModule> {
return {
ngModule: HttpClientModule,
providers: [
// taken from source code as of version 9
HttpClient,
{provide: HttpHandler, useClass: HttpInterceptingHandler},
HttpXhrBackend,
{provide: HttpBackend, useExisting: HttpXhrBackend},
BrowserXhr,
{provide: XhrFactory, useExisting: BrowserXhr},
// HttpClientXsrfModule providers
...HttpClientXsrfModule.forRoot().providers
]
}
}
}
Describe alternatives youāve considered
Other, perhaps more suitable or powerful solutions, are definitely more difficult to implement.
One might be to extend capabilities of multi interceptors (or add another multi special type) to be able to extend themselves with the array of the parent injector.
Lastly, in another train of thought, this problem may delve a little into the āproblemā that ModuleWithProviders
doesnāt solve thoroughly, being that provider inclusion is not completely controlled if the module in question imports another module that provides something. And even if the second module has a static ModuleWithProviders
method for the same argument, you canāt (not in a conventional manner) control which module version to import from within these methods.
i.e. ModuleWithProviders
canāt solve providers in deeper module imports with its intended design.
Hence, the most complicated solution would be to redesign this.
These are a lot less practical solutions, but since thereās the section, I might as well mention them.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:37
- Comments:8 (3 by maintainers)
Top GitHub Comments
Hello, itās been a while since I opened this issue as a feature request. Iāve seen some interactions, among them,
HttpHandler
level proposed implementation, and even calling it a bug (https://github.com/angular/angular/issues/39125). I wanted to say, I still see this as a framework design decision motivated by conceivable use cases. In that reasoning, I wrote an article commenting on some possibilities regarding that. Even uploaded a working example to github. So, youāre welcome to read. https://miguel-leon.medium.com/extending-http-interceptors-hierarchically-in-angular-4ca4d25af475Cheers!
Hi, thanks for the comment!
I realize now that I didnāt specify whether I meant āextending interceptorsā as in enlarging the main set of interceptors or as in having different sets of interceptors. I guess modifying the provider in my example a little would allow both cases.
But actually I meant neither (and both?). What I meant was for children module (lazy loaded) injectors to have its own set of interceptors but also benefit from the main ones (a hierarchy).
This was actually the use case in my project. I wanted my child module to apply the application wide interceptors, but also its own āprivateā set of interceptors. And in retrospective, I donāt know if it would have been all OK if this child module would have updated the main set of interceptors. Also the child module was a library (yes, a lazy loaded module in a library with Ivy).
In summary, I think both your set of rules and my use case can be achieved. But I wouldnāt want to see this feature restricted to only one way. I rather it to not change.
In any case, both ways have the same (lack of) difficulty to implement, and IMHO, I donāt see only one set of interceptors as a superior design, both designs have their pros and cons.
I hope I clarified some things. Thanks again! Regards.