I want to override Http
with a custom class, say HttpClient
to do some operations before a request and after a response, however I don't want to have to remember to import that class instead of the platform http class.
I've been experimenting with doing this via the 'multi' providers, but I can't quite make it click.
Here's my override class:
import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
@Injectable()
export class HttpClient {
private http: Http;
constructor(http: Http) {
this.http = http;
}
get(url) {
let headers = new Headers();
doSomethingToHeader(headers);
return this.http.get(url, {
headers: headers
});
}
}
And here's my main.ts
bootstrap(AppComponent, [
provide(HTTP_PROVIDERS, {useExisting: HTTP_PROVIDERS, multi: true}),
provide(HTTP_PROVIDERS, {useClass: HttpClient, multi: true})
]);
But when I try to call http.get() in my app, I get
ORIGINAL EXCEPTION: No provider for Http!
Any ideas? Am I going about this the wrong way?
Thanks!
UPDATE
I found this blog post. It pretty much describes what Gunter describes below. I'm accepting his answer.
multi: true
only works when the provider is designed to be a multi
provider like PLATFORM_DIRECTIVES
. HTTP_PROVIDERS
are not multi
providers, it's just a collection of individual providers.
What you can do is
bootstrap(AppComponent, [HTTP_PROVIDERS, {provide: Http, useClass: HttpClient}])
results in cycles (see comments)
This should work:
bootstrap(AppComponent, [
HTTP_PROVIDERS,
{
provide: Http,
useFactory: (backend, defaultOptions) => new HttpClient(new Http(backend, defaultOptions)),
deps: [XHRBackend, RequestOptions]
}
])
The important part is that your custom provider that overrides the provider defined in HTTP_PROVIDERS
comes after the one you want to override. Therefore it's important that HTTP_PROVIDERS
comes before {provide: Http, ...}
With multi: true
you don't override a provider but instead add another item to a provider that provides a set of values.