Mi piace l'idea di sostituire le opzioni predefinite, questa sembra una buona soluzione.
Tuttavia, se stai per estendere la Httpclasse. Assicurati di leggere tutto!
Alcune risposte qui mostrano in realtà un sovraccarico errato del request()metodo, che potrebbe portare a errori difficili da individuare e comportamenti strani. Mi sono imbattuto in questo io stesso.
Questa soluzione si basa sull'implementazione del request()metodo in angolare 4.2.x, ma dovrebbe essere compatibile con il futuro:
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;
}
}
Si noti che sto importando la classe originale in questo modo import { Http as NgHttp } from '@angular/http';per evitare conflitti di nomi.
Il problema affrontato qui è che il request()metodo ha due firme di chiamata diverse. Quando l' Requestoggetto viene passato anziché l'URL string, l' optionsargomento viene ignorato da Angular. Quindi entrambi i casi devono essere gestiti correttamente.
Ed ecco l'esempio di come registrare questa classe sovrascritta con il contenitore 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
);
}
Con tale approccio è possibile iniettare la Httpclasse normalmente, ma la classe sovrascritta verrà invece iniettata magicamente. Ciò consente di integrare facilmente la soluzione senza modificare altre parti dell'applicazione (polimorfismo in azione).
Basta aggiungere httpProvideralla providersproprietà dei metadati del modulo.