J'aime l'idée de remplacer les options par défaut, cela semble être une bonne solution.
Cependant, si vous souhaitez étendre la Http
classe. Assurez-vous de lire attentivement!
Certaines réponses ici montrent en fait une surcharge incorrecte de request()
méthode, ce qui pourrait entraîner des erreurs difficiles à détecter et un comportement étrange. Je suis tombé dessus moi-même.
Cette solution est basée sur l' request()
implémentation d'une méthode dans Angular 4.2.x
, mais devrait être compatible avec l'avenir:
import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';
import {
ConnectionBackend, Headers,
Http as NgHttp,
Request,
RequestOptions,
RequestOptionsArgs,
Response,
XHRBackend
} from '@angular/http';
import {AuthenticationStateService} from '../authentication/authentication-state.service';
@Injectable()
export class Http extends NgHttp {
constructor (
backend: ConnectionBackend,
defaultOptions: RequestOptions,
private authenticationStateService: AuthenticationStateService
) {
super(backend, defaultOptions);
}
request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
if ('string' === typeof url) {
url = this.rewriteUrl(url);
options = (options || new RequestOptions());
options.headers = this.updateHeaders(options.headers);
return super.request(url, options);
} else if (url instanceof Request) {
const request = url;
request.url = this.rewriteUrl(request.url);
request.headers = this.updateHeaders(request.headers);
return super.request(request);
} else {
throw new Error('First argument must be a url string or Request instance');
}
}
private rewriteUrl (url: string) {
return environment.backendBaseUrl + url;
}
private updateHeaders (headers?: Headers) {
headers = headers || new Headers();
// Authenticating the request.
if (this.authenticationStateService.isAuthenticated() && !headers.has('Authorization')) {
headers.append('Authorization', 'Bearer ' + this.authenticationStateService.getToken());
}
return headers;
}
}
Notez que j'importe la classe d'origine de cette façon import { Http as NgHttp } from '@angular/http';
afin d'éviter les conflits de noms.
Le problème abordé ici est que la request()
méthode a deux signatures d'appel différentes. Lorsque l' Request
objet est passé à la place de l'URL string
, l' options
argument est ignoré par Angular. Les deux cas doivent donc être traités correctement.
Et voici l'exemple de la façon d'enregistrer cette classe substituée avec le conteneur DI:
export const httpProvider = {
provide: NgHttp,
useFactory: httpFactory,
deps: [XHRBackend, RequestOptions, AuthenticationStateService]
};
export function httpFactory (
xhrBackend: XHRBackend,
requestOptions: RequestOptions,
authenticationStateService: AuthenticationStateService
): Http {
return new Http(
xhrBackend,
requestOptions,
authenticationStateService
);
}
Avec une telle approche, vous pouvez injecter la Http
classe normalement, mais votre classe surchargée sera injectée comme par magie. Cela vous permet d'intégrer facilement votre solution sans changer d'autres parties de l'application (polymorphisme en action).
Ajoutez simplement httpProvider
à la providers
propriété de vos métadonnées de module.