-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ignorable HttpClient Interceptors #20203
Comments
It is seams like the list of exclusions could be quite big so it might be look a bit weired to pass that as a parameter. Also you want sometimes not only exclude but include only. Custom decorator would look much nicer to approach that. My current solution that just checking the request url inside my interceptors and based on that I am making a decision to apply interceptor or not but always wanted to review that part. |
@kuncevic How do you see decorator usage here? We can decorate properties and functions/class declarations but I'm not sure about actual function call. Maybe both |
Duplicate of #18155 |
Interceptors are designed to intercept any action with exactly no exception. |
@jcimoch See #18155 (comment) for a way of achieving this. We have used this strategy and certain conventions to allow generic disabling of interceptors in our app on a per-request basis. @seedy I disagree. It really depends on your use cases. A typical example, where you would have this behavior is a loadingNotification. Implemented using an interceptor it can be transparently activated / de-activated across your whole app. But there are times, where you might not want, the global loading notification (that might be blocking), but a local one - maybe non-blocking and thus disable the interceptor for a certain request. Although I agree, that this should not be the focus of Angular. Allowing custom meta data to send along with each request is the broader solution, that can be used to achieve this. This seems to be planned -> #18155 |
@ChristianUlbrich App wise, I'd definitely not give the responsibility to an interceptor in your use case. In your use case it should really be the caller who knows which call should or should not trigger notifications - for instance - and wrap your application calls within them. Custom headers? I'd be against putting app logic in a custom header. You might someday end up having multiple particular cases, hence multiplying their number. I understand what you guys are looking for, but I feel like it's a very complicated way to answer the problem. Simple solution to me :
|
This isn't something we plan on implementing for interceptors currently (but feel free to try and convince me!) |
I've got a great reason. We get JWT tokens from a kerberos enabled endpoint, we pass those tokens to every other API call our application makes. An interceptor makes great sense here, but we need to be able to exclude the call that gets the token, otherwise we end up in a circular dependency. |
I worked around this by using window.fetch for the only call that needed to be excluded. |
@jabbera Just use the approach with custom headers. It isn't that complex. On a side note - from a security standpoint, you don't want your application to have access to the token. An app having access to auth tokens is prone to XSS attacks -> https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage . |
@seedy I strongly disagree with That is why they are used for thing like logging, auth or loading notifications. This is the reason why they are used by any 3rd party modules implementing a generic loading notification or auth logic without touching your existing code. Before interceptors you had to use a custom API / extended However this is OT, because this issue is not against Interceptors but for an option to ignore them through a specific API. |
Would it be possible to have interceptors declared as global (current behavior) and as local to an instance of HttpClient. The idea would be for a project to provide several httpClient using a factory with a list of activated interceptors For example i want to have a specific HttpClient instance for my Rest APIs and an other configured differently to call a partner's API. Different auth, different interceptor. We would not have to enable or ignore interceptor, just use the configured HttpClient. We could add or remove interceptors for a specific subset of requests with no impact on business code, only on the provider and injection dependency. For backward compatibility reasons, just keep current behavior of global interceptors. |
@jccazeaux It is possible, every httpClient instance gets own interceptors, I'm using the solution which is using this fact. I also enabled disabling particular interceptor by sending unique header metadata. But is still solution far from perfect. I think it should be possible to send additional data to interceptor like it was possible in angular 1.x. Even if for some reason people consider this as anit pattern it is still only the option and life would be much easier for some corner cases. I refactored my code and deleted all custom httpServices which were inheriting the httpModule in favour of simple HttpClient, it just simplifies a lot of things and most of a time we were creating wrapper around HttpModule to provide some default headers with every request etc. Now when we have interceptors we don't have to do that. Yet still one solution of the problem we are talking about here is to extend HttpClient again with custom implementation, but seriously it isn't the best pattern. I like to work with http api directly, not with some wrappers written to achieve simple things. |
I tried extending HttpClient, but as you say it's not a good idea. @jcimoch What do you mean by "every httpClient instance gets own interceptors". It's currently possible ? I think it may be possible to configure interceptors without using headers or metadat which are really intrusive. All should be possible with provider configuration. Isn't it? |
@jccazeaux ... when you import
|
OK, but on a same module we cannot have several httpClients with different interceptors. I don't know if i'm clear about the idea |
@jccazeaux ... hmm, why do want that at all? The interceptors should be written to understand what should they do ... |
Because i don't want my interceptors to apply to all my requests. I have a mid size web application which has several REST backends
For my application to be maintainable I need 3 different HttpClients with 3 configurations
Tomorrow, the partner will have CSRF. I will have to activate it with minimal code impact.
For sure, if you don't have mutliple backends, this would be totally useless. But for mid-size business apps this will be useful. In our previous (internal) framework, we add this and it revealed to be very useful. A complete framework as Angular should (IMHO) have this kind of stuff NB : servers for each backend is not predictable and depends on user. So it cannot be used in interceptor to filter |
@jccazeaux ... I understand your arguments ... actually using a lazy loaded module with importing the HttpClientModule means creating a new HttpClient instance + the possibility to provide its own set of interceptors on that module level. It would mean that you have to have a separate lazy loaded module (+ its services) for each extra API you need. Although technically it will work smoothly I am not sure if it is the best solution. Maybe it would be better to consult this theme with the author of HttpClientModule ... @alxhub ... he is present very often on Gitter channel so it shouldn't be a problem to reach him. |
@mlc-mlapis I'm working on a design to allow registration of interceptors in lazy loaded modules, but they would be installed globally so there'd still be a single set of interceptors in the application. I don't like the way it works currently, where you can accidentally bind |
@alxhub ... I understand your idea ... but still I am trying to imagine what would be possible to do to allow a creation of sets of interceptors ... identifying them and allowing to use optionally their ids to control which set should be called ... default would be still = calling all interceptors. |
@mlc-mlapis multiple sets of interceptors will do the job nicely too ! @alxhub do you think it is possible? |
@ChristianUlbrich thanks for the link about localstorage versus cookie for the token! I'll look into it. |
@ChristianUlbrich Can't use HttpClient from within an interceptor because it's a circular dependency. Still stuck with fetch unless you have another idea. I tried chaining the calls together but they fire out of order. (IE: the token is not in local storage before the original call fires)
|
Is it needed to be complicated? Why not just skip urls? (I'm newbie in angular) if (excludedUrl.some(x => x === req.url)) { |
jabbera Try to decomposite your service from where you try to get the token. I resolved that problem by removing all calls to HttpClient from service with token logic and new service deals only with tokens, without requests to http. |
@OlegBabkin This will work with our own interceptors, but not with community interceptors. And with many interceptors on many applications with many urls, it will soon become pretty complicated. On backend I can have this configuration possibilities with Spring's RestTemplate which allows to instantiate as many as needed, each with a set of interceptors. @Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
restTemplate.setInterceptors(Collections.singletonList(new XUserAgentInterceptor()));
return restTemplate;
} Is it possible to have something similar in Angular? |
I just encountered the same problem, in my interceptor I need to do a HTTP request to get a new token :( |
@alxhub ... once more about sets of interceptors ...
The idea of a single set of interceptors in the application = all are installed globally (including those defined in any lazy loaded module) is generally fine and to allow easy filtering and using sub-sets of interceptors the following would be enough:
|
@alxhub Just thought of something. If interceptors declared in lazy loaded modules become global when the module is loaded, it will lead to strange behaviour where ajax requets will not behave the same depending on the user navigation. I'm still conviced Angular should allow to define sets of interceptors, @mlc-mlapis describes it well. Is it considered ? |
I have to agree with @jccazeaux, this is really bad idea |
For anyone else looking for a solution. I found the solution by navigating to the definition of the http handler that is used as an argument for the constructor of the HttpClient.
If you look at the commentary of the HttpBackend you might notice this very important message:
So I got it working properly doing it like this:
HttpBackend is injected by Angular and this does indeed not call the interceptor. |
Thank you so much for this last post. That is exactly the scenario I needed to exclude a global bearer token interceptor to be called on the end point requesting the token. Thanks. |
I changed the logic a bit to this:
And then added it to my module:
And use it like this:
|
any update regarding this ? |
@TheSilvermind solution works great, and in my opinion a very clean way to exclude an interceptor being called. Thanks! |
@TheSilvermind Thanks for this solution. I'm concerned though that this is not a sustainable long term solution as the api might change. |
@alexmgrant You're welcome and I agree with your concerns. I think this is not an issue until it really becomes one. Also I think it is better to use the second implementation I suggested, so you can swap out with a custom client of your own when the BackendHandler is no longer usable in this manner. The only reason I use this method is so I don't have to write my own handler :). If the time comes I will have to do some work to write my own, but until then I gladly rely on the built-in system. |
I have managed this in a simple way Here is my solution for this. if (req.url.indexOf('http://') < 0 ) { |
Hey Folks, I'm facing an very similar issue, I need for different communication with backend services different interceptors. Previously the old After a good read of this article from @MaximusK I come up with this solution:
After registering the
I don't know if the abstraction of the |
@TheSilvermind - if I understand your solution of using HttpBackend, that skips all interceptors. Do you have a mechanism for still allowing some interceptors to be executed? In my scenario, I have an interceptor for caching (similar to the TOH example) and I want to have the ability to disable caching for some requests. But I can't turn off all interceptors since I have others that are needed. |
As I've mentioned before the support to ignore Interceptors should not be in the core. We should "fight" for #18155, because allowing to pass misc data to interceptors allows for way more use cases than simply plainly ignoring certain interceptors. If you must have this functionality it is trivial to add it right now. Either wrap httpClient with some sugar methods that allow ignoring certain Interceptors (per-request approach), or make your Interceptors aware of certain URLs they should be disabled for by themselves (whitelist approach). Or combine both approaches. |
@ChristianUlbrich I'm personally fine with #18155, it makes sense. Actually, I decided to implement one of the suggested solutions from there by @JWess - #18155 (comment). Not sure if it's the best to rely on the params but it looks like it should work. Open to ideas for alternatives till a complete core solution is made available in Angular. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a...
Current behavior
In current angular 5 implementation there is no elegant way to ignore particular http interceptor.
Expected behavior
It would be nice to be able to pass additional option as array of interceptors we whish to ignore for particual request.
It could be done like so
What is the motivation / use case for changing the behavior?
You may ask why do you want to ignore it in a first place? Well there are multiple usecases, for example your application may be composed of different feature modules which act like standalone applications. Each of these modules has own submodules. You may want to use authentication interceptor for all submodules but one http call may need different authorization header than others. To solve this we can create another submodule which won't have all interceptors included but it can end up in many unnecessary submodules. Another approach (which I'm using now) is to write interceptor in a special fashion where before applying transformation on http call I look for unique header with id values, each id represent an interceptor, if id match, then I simply return from the function and do not perform transformations at all. This solution works but requires additional overhead while implementing interceptor and setting special header when we want to ignore it.
I'm willing to help and contribute with such functionality on my own. I just need to be sure that I have team and community blessing to start work on that ;)
The text was updated successfully, but these errors were encountered: