Ich mag die Idee, Standardoptionen zu überschreiben, dies scheint eine gute Lösung zu sein.
Wenn Sie jedoch die Http
Klasse erweitern möchten. Lesen Sie dies unbedingt durch!
Einige Antworten hier zeigen tatsächlich eine falsche Überladung der request()
Methode, was zu schwer zu fassenden Fehlern und seltsamem Verhalten führen kann. Ich bin selbst darauf gestoßen.
Diese Lösung basiert auf der request()
Methodenimplementierung in Angular 4.2.x
, sollte jedoch zukunftskompatibel sein:
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;
}
}
Beachten Sie, dass ich die ursprüngliche Klasse auf diese Weise importiere import { Http as NgHttp } from '@angular/http';
, um Namenskonflikte zu vermeiden.
Das hier angesprochene Problem besteht darin, dass die request()
Methode zwei verschiedene Anrufsignaturen aufweist. Wenn ein Request
Objekt anstelle der URL übergeben wird string
, wird das options
Argument von Angular ignoriert. Beide Fälle müssen also ordnungsgemäß behandelt werden.
Und hier ist das Beispiel, wie diese überschriebene Klasse im DI-Container registriert wird:
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
);
}
Mit einem solchen Ansatz können Sie die Http
Klasse normal injizieren , aber Ihre überschriebene Klasse wird stattdessen magisch injiziert. Auf diese Weise können Sie Ihre Lösung einfach integrieren, ohne andere Teile der Anwendung zu ändern (Polymorphismus in Aktion).
Fügen Sie einfach httpProvider
die providers
Eigenschaft Ihrer Modul-Metadaten hinzu.