Me gusta la idea de anular las opciones predeterminadas, esto parece una buena solución.
Sin embargo, si estás dispuesto a extender la Http
clase. ¡Asegúrate de leer esto!
Algunas respuestas aquí en realidad muestran una sobrecarga incorrecta del request()
método, lo que podría conducir a errores difíciles de detectar y un comportamiento extraño. Me he topado con esto yo mismo.
Esta solución se basa en la request()
implementación del método en Angular 4.2.x
, pero debería ser compatible con el 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;
}
}
Tenga en cuenta que estoy importando la clase original de esta manera import { Http as NgHttp } from '@angular/http';
para evitar conflictos de nombres.
El problema abordado aquí es que el request()
método tiene dos firmas de llamada diferentes. Cuando Request
se pasa el objeto en lugar de la URL string
, options
Angular ignora el argumento. Entonces ambos casos deben ser manejados adecuadamente.
Y aquí está el ejemplo de cómo registrar esta clase anulada con el contenedor 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 este enfoque, puede inyectar la Http
clase normalmente, pero su clase anulada se inyectará mágicamente en su lugar. Esto le permite integrar su solución fácilmente sin cambiar otras partes de la aplicación (polimorfismo en acción).
Simplemente agregue httpProvider
a la providers
propiedad de los metadatos de su módulo.