Mi piace l'idea di sostituire le opzioni predefinite, questa sembra una buona soluzione.
Tuttavia, se stai per estendere la Http
classe. 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' Request
oggetto viene passato anziché l'URL string
, l' options
argomento 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 Http
classe 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 httpProvider
alla providers
proprietà dei metadati del modulo.