Angular 2
Interceptor Http
Buscar..
Observaciones
Lo que hacemos con la clase HttpServiceLayer es extender la clase Http desde angular y agregarle nuestra propia lógica.
Luego inyectamos esa clase en la clase bootstrap de la aplicación y le decimos a Angular que importamos la clase Http, en la parte posterior para insertar HttpServiceLayer.
En cualquier parte del código podemos simplemente importar
import { Http } from '@angular/http';
Pero nuestra clase será utilizada para cada llamada.
Clase simple Extendiendo la clase Http de Angular
import { Http, Request, RequestOptionsArgs, Response, RequestOptions, ConnectionBackend, Headers } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/empty';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import { ApplicationConfiguration } from '../application-configuration/application-configuration';
/**
* This class extends the Http class from angular and adds automaticaly the server URL(if in development mode) and 2 headers by default:
* Headers added: 'Content-Type' and 'X-AUTH-TOKEN'.
* 'Content-Type' can be set in any othe service, and if set, it will NOT be overwritten in this class any more.
*/
export class HttpServiceLayer extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router, private appConfig: ApplicationConfiguration) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
this.getRequestOptionArgs(options);
return this.intercept(super.request(this.appConfig.getServerAdress() + url, options));
}
/**
* This method checks if there are any headers added and if not created the headers map and ads 'Content-Type' and 'X-AUTH-TOKEN'
* 'Content-Type' is not overwritten if it is allready available in the headers map
*/
getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
if (!options.headers.get('Content-Type')) {
options.headers.append('Content-Type', 'application/json');
}
if (this.appConfig.getAuthToken() != null) {
options.headers.append('X-AUTH-TOKEN', this.appConfig.getAuthToken());
}
return options;
}
/**
* This method as the name sugests intercepts the request and checks if there are any errors.
* If an error is present it will be checked what error there is and if it is a general one then it will be handled here, otherwise, will be
* thrown up in the service layers
*/
intercept(observable: Observable<Response>): Observable<Response> {
// return observable;
return observable.catch((err, source) => {
if (err.status == 401) {
this._router.navigate(['/login']);
//return observable;
return Observable.empty();
} else {
//return observable;
return Observable.throw(err);
}
});
}
}
Usando nuestra clase en lugar de Http de Angular
Después de extender la clase Http, necesitamos decirle a angular que use esta clase en lugar de la clase Http.
Para hacer esto, en nuestro módulo principal (o según las necesidades, solo un módulo en particular), debemos escribir en la sección de proveedores:
export function httpServiceFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions, router: Router, appConfig: ApplicationConfiguration) {
return new HttpServiceLayer(xhrBackend, requestOptions, router, appConfig);
}
import { HttpModule, Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers } from '@angular/http';
import { Router } from '@angular/router';
@NgModule({
declarations: [ ... ],
imports: [ ... ],
exports: [ ... ],
providers: [
ApplicationConfiguration,
{
provide: Http,
useFactory: httpServiceFactory,
deps: [XHRBackend, RequestOptions, Router, ApplicationConfiguration]
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
Nota: ApplicationConfiguration es solo un servicio que utilizo para guardar algunos valores durante la duración de la aplicación.
Simple HttpClient AuthToken Interceptor (Angular 4.3+)
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { UserService } from '../services/user.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthHeaderInterceptor implements HttpInterceptor {
constructor(private userService: UserService) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.userService.isAuthenticated()) {
req = req.clone({
setHeaders: {
Authorization: `Bearer ${this.userService.token}`
}
});
}
return next.handle(req);
}
}
Proporcionar Interceptor (some-module.module.ts)
{provide: HTTP_INTERCEPTORS, useClass: AuthHeaderInterceptor, multi: true},