Imaginons que je veux que TOUTES mes requetes vers le serveur ai un headers avec des infos particulieres. Nous allons utiliser un service Intercept() qu vas 'intercepter' nos requetes avant qu'elles quittent l'application et lui appliquer une fonction.
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
export class AuthInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log('request is on its way');
return next.handle(req);
}
};
// Bien penser a le rajouter dans les providers de notre app.module.ts:
providers: [{provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptorService,
multi: true}],
Et si je veux réagir a la réponse de mon serveur ? A la suite de la méthode handle nous pouvons rajouter un pipe() et traiter notre réponse :
return next.handle(req).pipe(tap(
(event) => {
console.log(event);
if (event.type === HttpEventType.Response) {
console.log('response arrive, body data :');
console.log(event.body);
}
}
));
// console :
log(event) ==>
HttpResponse {headers: HttpHeaders, status: 200,
statusText: "OK", url: "<https://recettes-courses.firebaseio.com/posts.json?print=pretty>", ok: true, …}
response arrive, body data :
log(event.body) ==>
-M4nXVZNLaAOtlC1Kq_W:
content: "La plus belle"
title: "Lison"
Autre exemple :
export class LoginInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log('Outgoing Request.. ');
console.log(req.url);
return next.handle(req).pipe(tap(
(event) => {
if (event.type === HttpEventType.Response) {
console.log('Incoming response ..');
console.log(event.body);
}
}
));
}
}
//console :
Outgoing Request..
<https://recettes-courses.firebaseio.com/posts.json>
Incoming response ..
{name: "-M4nbVnx8ZEY7ORabBJV"}
@Injectable()
export class AuthInterceptorService implements HttpInterceptor {
constructor(private authService: AuthService, private store: Store<fromApp.AppState>) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
return this.store.select('auth').pipe(
take(1),
map(authState => {
return authState.user;
}),
exhaustMap(user => {
if (!user) {
return next.handle(req);
}
const modifiedReq = req.clone({
params: new HttpParams().set('auth', user.token)
});
return next.handle(modifiedReq);
})
);
}
}
/**
* @ngdoc constant
* @name httpInterceptor
* @description
* Gestion des requêtes et réponses http
* @param {provider} $httpProvider provider angular permettant gestion des requêtes http
* @param {provider} $provide permet d'utiliser $injector
* @param {service} UserService service permettant de récupérer les donnéees de l'utilisateur connecté
*/
angular.module('core.interceptor', ['core.services.modal'])
.constant('httpInterceptor', function ($httpProvider, $provide,
$http
) {
'use strict';
/**
* @ngdoc factory
* @name mobigestionInterceptor
* @description
* Intercepteur des requêtes et réponses http : initialise $httpProvider.interceptors
* @param {provider} $q permet d'effectuer une requête asynchrone. Renvoi une promise.
* @param {provider} $injector permet d'injecter mes services en tant que providers
* @param {service} constants service permettant de récupérer les donnéees de l'utilisateur connecté
* @param {service} $rootScope
*/
$provide.factory('mInterceptor', function ($q, $injector, constants, $rootScope,$timeout) {
'ngInject';
return {
'request': function (config) {
config.timeout = constants.timeout;
if (config.url.indexOf(constants.server) > -1) {
config.headers['Content-Type'] = 'application/json';
config.headers.Accept = null;
var user = $injector.get('UserService').getUserConnected();
if (user) {
config.data.contexteUsr = $injector.get('UserService').getContext(user,config);
}
// pour les traitements avec confirmation...
if (config.data.resolveFunc) {
config.resolveFunc=config.data.resolveFunc;
delete config.data.resolveFunc;
}
if (config.data.errorFunc) {
config.errorFunc=config.data.errorFunc;
delete config.data.errorFunc;
}
// pour les traitements synchrones, donc avec timeout infini...
if(config.data.noTimeOut) {
config.timeout=0;
delete config.data.noTimeOut;
$injector.get('MsModalService').showWaitPopup(true);
}
// ensuite on compresse la requête dans le cas OU sa taille est supérieure a 1000 chars...
// sinon l'intérêt est limité....
var lrequest=angular.toJson(config.data);
if (lrequest.length>(constants.gzipMinLength?constants.gzipMinLength:1000)) {
config.headers['Content-Encoding'] = 'gzip';
config.data=pako.gzip(lrequest);
config.transformRequest=[];
}
}
return config;
},
'response': function (response) {
var hasReport=((angular.isDefined(response.data))&&(angular.isDefined(response.data.rapport)&&(angular.isArray(response.data.rapport))&&(response.data.rapport.length>0))),hasTimeOut=false,lfunc;
if (angular.isDefined(response.config)) {
if (response.config.timeout===0) {
hasTimeOut=true;
$injector.get('MsModalService').closeWaitPopup();
}
if (response.config.resolveFunc) {
lfunc=response.config.resolveFunc;
delete response.config.resolveFunc;
if (!hasReport) {
if (lfunc.owner) {
lfunc.func(response,lfunc.owner,lfunc.params);
} else {
lfunc(response);
}
}
}
}
if ((angular.isDefined(response.data))&&(angular.isDefined(response.data.messageList))&&(angular.isArray(response.data.messageList))&&(response.data.messageList.length>0)) {
var i;
for(i=0;i<response.data.messageList.length;i++) {
$rootScope.$broadcast('http-message', response.data.messageList[i]);
}
} else {
if ((angular.isDefined(response.data))&&(angular.isDefined(response.data.message))) {
$rootScope.$broadcast('http-message', response.data.message);
}
}
if (hasReport) {
$rootScope.$broadcast('http-report', {report:response.data.rapport,resolveFunc:lfunc,response:response});
}
return response;
},
'responseError': function (rejection) {
if (angular.isDefined(rejection.config)) {
var closewaitpopup=true;
var broadcasttype='';
var error={title:'',detail:'',config:undefined};
var errorData,lfunc;
var hasReport=false;
if (rejection.config.url.indexOf(constants.server) > -1) {
if ((rejection.config.responseType==="arraybuffer")&&(rejection.data!==undefined)&&(rejection.data.constructor===ArrayBuffer)) {
// on essaye de le transformer en JSON...
var encodedString = String.fromCharCode.apply(null, new Uint8Array(rejection.data)),
decodedString = decodeURIComponent(escape(encodedString));
errorData=angular.fromJson(decodedString);
} else if ((rejection.data)&&(rejection.data.erreur)) {
errorData=rejection.data;
}
if (errorData) {
hasReport=((angular.isDefined(errorData))&&(angular.isDefined(errorData.erreur))&&(angular.isDefined(errorData.erreur.rapport))&&(angular.isArray(errorData.erreur.rapport))&&(errorData.erreur.rapport.length>0));
if ((errorData.erreur.code==='MSG_COMMUN_008')||(errorData.erreur.code==='MSG_COMMUN_USER_008')) {
broadcasttype='connection-error';
error.title=$injector.get('LibelleService').getCoreLib('core.common.msg.errConnLib');
} else {
if ((errorData.erreur.niveauErreur)&&(errorData.erreur.niveauErreur==='confirm')) {
broadcasttype='http-confirm';
error.title=errorData.erreur.code;
error.detail=errorData.erreur.lib;
error.config=rejection.config;
} else {
broadcasttype='http-error';
error.title=$injector.get('LibelleService').getCoreLib('core.common.msg.errServLib');
error.detail=errorData.erreur.lib;
if ((angular.isDefined(errorData.erreur.precision))&&(angular.isArray(errorData.erreur.precision))) {
var precision=errorData.erreur.precision;
for (var i=0;i<precision.length;i++) {
error.detail+='\\n'+ ( precision[i].displayName ? precision[i].displayName : precision[i].champ)+' : '+precision[i].lib;
}
} else {
error.detail+=' (' + errorData.erreur.code + ')';
}
}
}
} else {
broadcasttype='http-error';
error.title=$injector.get('LibelleService').getCoreLib('core.common.errTimeoutLib');
error.detail=$injector.get('LibelleService').getCoreLib('core.common.msg.errTimeoutLib');
}
if ((rejection.status === 403)||(rejection.status === 401)) {
error.title=$injector.get('LibelleService').getCoreLib('core.common.errAutLib');
var user = $injector.get('UserService').getUserConnected();
if (!user) {
broadcasttype='connection-error';
}
}
if (rejection.status === 404) {
error.title=$injector.get('LibelleService').getCoreLib('core.common.errPageLib');
}
if (rejection.status === 413) {
error.title=$injector.get('LibelleService').getCoreLib('core.common.errTailleLib');
}
if (broadcasttype!=='') {
if (rejection.config.timeout===0) {
closewaitpopup=false;
$injector.get('MsModalService').closeWaitPopup(true).then(function(closeresult) {
$rootScope.$broadcast(broadcasttype, error);
});
} else {
$rootScope.$broadcast(broadcasttype, error);
}
}
}
if ((closewaitpopup)&&(rejection.config.timeout===0)) {
$injector.get('MsModalService').closeWaitPopup();
}
/**
on exécute la callback s'il y a erreur...
**/
if ((broadcasttype!=='http-confirm')&&(rejection)&&(rejection.config)&&(rejection.config.errorFunc)) {
if (rejection.config.errorFunc) {
lfunc=rejection.config.errorFunc;
delete rejection.config.errorFunc;
if (!hasReport) {
if (lfunc.owner) {
lfunc.func(rejection,lfunc.owner,lfunc.params);
} else {
lfunc(rejection);
}
}
}
}
if ((hasReport)&&(broadcasttype!=='http-confirm')) {
$rootScope.$broadcast('http-report', {report:errorData.erreur.rapport,resolveFunc:undefined,response:rejection});
}
}
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('mInterceptor');
});
import { Injectable } from '@angular/core';
import {
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse, HttpResponse
} from '@angular/common/http';
import { Observable, throwError, TimeoutError, MonoTypeOperatorFunction, of } from 'rxjs';
import { catchError, timeout, tap, switchMap, mapTo, switchMapTo } from 'rxjs/operators';
import { HttpPostResult } from 'projects/common/src/lib/http-module/models/http-post-result';
import { ConstantsService } from '../../../../common/src/lib/constants/services/constants.service';
import { Constants } from '../../../../common/src/lib/constants/models/constants';
import { UserService } from '../../../../common/src/lib/user-module/services/user.service';
import { HttpPostContext } from '../../../../common/src/lib/http-module/models/http-post-context';
import { HttpPostBody } from '../../../../common/src/lib/http-module/models/http-post-body';
import { msIsDefined } from '../../../../common/src/lib/utils/class-utils';
import { MsHttpParams } from '../../../../common/src/lib/http-module/models/ms-http-params';
import { LibelleService } from '../../../../common/src/lib/user-module/services/libelle.service';
import { HttpPostResultError } from '../../../../common/src/lib/http-module/models/http-post-result-error';
import { MsBool } from '../../../../common/src/lib/http-module/models/ms-bool';
import { DisconnectService } from '../../../../common/src/lib/user-module/services/disconnect.service';
import { MsHttpUtils } from '../../../../common/src/lib/http-module/utils/ms-http-utils';
import { StandardModalService } from '../../../../common/src/lib/core-module/services/standard-modal.service';
import { ToastType, ToastService } from 'projects/common/src/lib/http-module/services/toast.service';
@Injectable()
/**
* HttpInterceptor des APIs
*/
export class MsBaseHttpInterceptorService implements HttpInterceptor {
protected static VERSION : string='1.0';
private constants : Constants;
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let ltimeout=this.constants.getTimeOut();
let lNoWaitPopup : boolean=false;
let lParams : MsHttpParams;
// on rajoute la version, le contexte etc.
if (req.url.indexOf(this.constants.getServer())>-1) {
// on regarde si dans le body j'ai un httpParams...
let lreqBody : HttpPostContext | HttpPostBody<any> = {...req.body};
if (msIsDefined(lreqBody.httpParams)) {
lParams=lreqBody.httpParams;
ltimeout=lParams.noTimeOut?undefined:ltimeout;
lNoWaitPopup=lParams.noWaitPopup;
if ((!ltimeout)&&(!lNoWaitPopup)) {
this.modalService.showWaitPopup();
};
delete lreqBody.httpParams;
}
// on rajoute le contexte Usr
lreqBody.contexteUsr=this.userService.getContext();
// on modifie les entêtes
req=req.clone({headers:req.headers.set('Content-Type', 'application/json'),body:lreqBody});
/*var lreqStr=JSON.stringify(lreqBody);
if (lreqStr.length>1000) {
req=req.clone({body:pako.gzip(lreqStr),headers:req.headers.set('Content-Encoding','gzip')});
}*/
}
return next.handle(req)
.pipe(
timeoutWhen(ltimeout?true:false,ltimeout),
switchMap(event =>
{
if ((event instanceof HttpResponse)) {
if ((req.url.indexOf(this.constants.getServer())>-1)&&(msIsDefined(event.body))&&(req.responseType==="json")) {
let l_body=MsHttpUtils.getBody(event.body,req.responseType);
if ((l_body)&&(l_body.rapport)&&(l_body.rapport.length>0)) {
if ((!ltimeout)&&(!lNoWaitPopup)) {
return this.modalService.hideWaitPopup(true).pipe(
switchMapTo(
this.modalService.showActionReport({report:l_body.rapport}).pipe(
mapTo(event)
)
)
)
} else {
return this.modalService.showActionReport({report:l_body.rapport}).pipe(
mapTo(event)
)
}
} else {
if ((!ltimeout)&&(!lNoWaitPopup)) {
return this.modalService.hideWaitPopup(true).pipe(
mapTo(event)
)
} else {
return of(event);
}
}
} else {
if ((!ltimeout)&&(!lNoWaitPopup)) {
return this.modalService.hideWaitPopup(true).pipe(
mapTo(event)
)
} else {
return of(event);
}
}
} else {
return of(event);
}
}),
tap(event => {
if (event instanceof HttpResponse) {
if ((msIsDefined(event.body))&&(req.responseType==="json"))
{
let lbody : HttpPostResult<any>={...event.body};
if (msIsDefined(lbody.messageList) && (lbody.messageList.length>0)) {
for (let lmessage of lbody.messageList) {
var lwarning=(msIsDefined(lmessage.warning))&&((lmessage.warning===MsBool.TRUE)||(lmessage.warning===1));
if (lwarning) {
this.toastService.doToast(lmessage.lib,this.libelleService.getCoreLib('core.common.msg.avertServLib'),ToastType.WARNING);
} else {
this.toastService.doToast(lmessage.lib,this.libelleService.getCoreLib('core.common.msg.infoServLib'),ToastType.INFO);
}
}
} else if (msIsDefined(lbody.message)) {
var lwarning=(msIsDefined(lbody.message.warning))&&((lbody.message.warning===MsBool.TRUE)||(lbody.message.warning===1));
if (lwarning) {
this.toastService.doToast(lbody.message.lib,this.libelleService.getCoreLib('core.common.msg.avertServLib'),ToastType.WARNING);
} else {
this.toastService.doToast(lbody.message.lib,this.libelleService.getCoreLib('core.common.msg.infoServLib'),ToastType.INFO);
}
} else if ((lParams)&&(lParams.doToastSuccess)) {
this.toastService.doToast(this.libelleService.getCoreLib('core.common.msg.enregSucLib'),
this.libelleService.getCoreLib('core.common.msgLib'),ToastType.SUCCESS);
}
} else if ((lParams)&&(lParams.doToastSuccess)) {
this.toastService.doToast(this.libelleService.getCoreLib('core.common.msg.enregSucLib'),
this.libelleService.getCoreLib('core.common.msgLib'),ToastType.SUCCESS);
}
}
return event;
}),
catchError((error: HttpErrorResponse) => {
// gestion erreur de timeout
let lerror : HttpPostResultError
if (error instanceof TimeoutError) {
this.toastService.doToast(this.libelleService.getCoreLib('core.common.msg.errTimeoutLib'), this.libelleService.getCoreLib('core.common.errTimeoutLib'),ToastType.ERROR);
} else if (error instanceof HttpErrorResponse) {
if (req.url.indexOf(this.constants.getServer())>-1) {
lerror=MsHttpUtils.getError(error.error,req.responseType);
if ((lerror)&&((lerror.code==='MSG_COMMUN_008')||((lerror.code==='MSG_COMMUN_USER_008')))) {
this.disconnectService.doDisconnect().subscribe(
response => {
if ((response instanceof HttpResponse)&&(response.status===200)) {
window.location.replace("/login.html");//+getVersion());
}
}
);
} else {
switch (error.status) {
case 404 : this.toastService.doToast(this.libelleService.getCoreLib('core.common.msg.errRouteLib'), this.libelleService.getCoreLib('core.common.errRouteLib'),ToastType.ERROR);
break;
case 403 :
case 401 : this.toastService.doToast(this.libelleService.getCoreLib('core.common.msg.errAutLib'), this.libelleService.getCoreLib('core.common.errAutLib'),ToastType.ERROR);
break;
case 413 : this.toastService.doToast(this.libelleService.getCoreLib('core.common.msg.errAutLib'), this.libelleService.getCoreLib('core.common.errAutLib'),ToastType.ERROR);
break;
default :
if ((lerror)&&(lerror.niveauErreur!=='confirm')) {
this.doError(lerror);
} else {
console.error(error);
}
}
}
}
} else {
console.error(error);
}
if ((lerror)&&(lerror.rapport)&&(lerror.rapport.length>0)) {
if ((!ltimeout)&&(!lNoWaitPopup)) {
return this.modalService.hideWaitPopup(true).pipe(
switchMapTo(
this.modalService.showActionReport({report:lerror.rapport}).pipe(
switchMapTo(throwError(error))
)
)
)
} else {
return this.modalService.showActionReport({report:lerror.rapport}).pipe(
switchMapTo(throwError(error))
)
}
} else {
if ((!ltimeout)&&(!lNoWaitPopup)) {
return this.modalService.hideWaitPopup(true).pipe(
switchMapTo(throwError(error))
)
} else {
return throwError(error);
}
}
}));
}
protected doError(a_error:HttpPostResultError) : void {
let lmsg : string=this.libelleService.getCoreLib('core.common.msg.errServLib');
if (a_error) {
lmsg=a_error.lib;
if ((msIsDefined(a_error.precision))&&((a_error.precision.length>0))) {
for (let i of a_error.precision) {
lmsg+='\\n'+ ( i.displayName ? i.displayName : i.champ)+' : '+i.lib;
}
} else {
lmsg+=' (' + a_error.code + ')';
}
}
this.toastService.doToast(lmsg,this.libelleService.getCoreLib('core.common.msg.errServLib'),ToastType.ERROR);
}
constructor(private toastService : ToastService, constantsService : ConstantsService,
private userService : UserService, private libelleService : LibelleService,
private disconnectService : DisconnectService,
private modalService : StandardModalService) {
this.constants=constantsService.getConstants();
}
}
export function timeoutWhen<T>(cond: boolean,due: number | Date): MonoTypeOperatorFunction<T> {
return function(source: Observable<T>): Observable<T> {
return cond ? source.pipe(timeout(due)) : source;
}
}