Improve Error interceptor

master
Max Ehrlicher-Schmidt 4 years ago
parent 4a09780ec3
commit cc5945a8cf

@ -1,23 +1,17 @@
import { NgModule } from '@angular/core';
import { APOLLO_OPTIONS } from 'apollo-angular';
import {
ApolloClientOptions,
InMemoryCache,
} from '@apollo/client/core';
import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core';
import { environment } from '../environments/environment';
import { DefaultOptions } from '@apollo/client/core/ApolloClient';
import { onError } from '@apollo/link-error';
import {Apollo, gql} from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { SnackBarService } from './services/snackbar.service';
import { getErrorMessage } from './helper/getErrorMessage';
const uri = environment.apiUrl + '/graphql'; // <-- add the URL of the GraphQL server here
const defaultOptions: DefaultOptions = {
watchQuery: {
fetchPolicy: 'no-cache',
@ -27,27 +21,22 @@ const defaultOptions: DefaultOptions = {
fetchPolicy: 'no-cache',
errorPolicy: 'all',
},
}
export function createApollo(httpLink: HttpLink, snackBar: SnackBarService): ApolloClientOptions<any> {
};
export function createApollo(
httpLink: HttpLink,
snackBar: SnackBarService
): ApolloClientOptions<any> {
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) => {
snackBar.openSnackBar(JSON.stringify(message), "Ok", true);
/*console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
)*/
},
if (graphQLErrors) {
snackBar.openSnackBar(getErrorMessage(graphQLErrors[0] || null), 'Ok', true);
}
);
if (networkError) {
//console.log(`[Network error]: ${networkError}`);
// THE FOLLOWING CODE IS UNTESTED
//snackBar.openSnackBar("Ein NetzwerkFehler ist aufgetreten", "Ok", true, [{"message": networkError}] );
snackBar.openSnackBar(JSON.stringify(networkError), "", true);
snackBar.openSnackBar(JSON.stringify(networkError), '', true);
}
});
@ -64,9 +53,7 @@ export function createApollo(httpLink: HttpLink, snackBar: SnackBarService): Apo
provide: APOLLO_OPTIONS,
useFactory: createApollo,
deps: [HttpLink, SnackBarService],
}
},
],
})
export class GraphQLModule {
}
export class GraphQLModule {}

@ -0,0 +1,17 @@
export function getErrorMessage(error: any): string {
const message =
error?.error?.errors[0]?.message ||
error?.error?.message ||
error?.message ||
'';
if (
message.includes('not provided') ||
message.includes('violates not-null constraint')
) {
return 'Nicht alle benötigten Felder wurden ausgefüllt.';
}
if (message.includes("TimeFrames with ids") && message.includes("overlapping")) {
return "Überlappende Zeitscheibe - Ein Lastenrad kann zu einem Zeitpunkt nur an einem Standort stehen."
}
return message || 'Es ist ein Fehler aufgetreten. Prüfen Sie Ihre Eingaben oder versuchen Sie es später erneut.';
}

@ -1,92 +1,98 @@
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpErrorResponse,
} from '@angular/common/http';
import { AuthService } from '../services/auth.service';
import { Observable, throwError, BehaviorSubject } from 'rxjs';
import { catchError, filter, take, switchMap } from 'rxjs/operators';
import { SnackBarService } from '../services/snackbar.service';
import { Router, RouterStateSnapshot } from '@angular/router';
import { JsonPipe } from '@angular/common';
import { getErrorMessage } from './getErrorMessage';
@Injectable({
providedIn: 'root',
}
)
})
export class TokenInterceptor implements HttpInterceptor {
private isRefreshing = false;
private requestTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private authService: AuthService, private snackBar : SnackBarService, private router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
private requestTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
null
);
constructor(
private authService: AuthService,
private snackBar: SnackBarService,
private router: Router
) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
//console.log("i intercepted something");
if (this.authService.getRequestToken()) {
request = this.addToken(request, this.authService.getRequestToken());
}
return next.handle(request).pipe(catchError((error: HttpErrorResponse) => {
return next.handle(request).pipe(
catchError((error: HttpErrorResponse) => {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
//client error
//console.log("Client Error: " + JSON.stringify(error));
errorMessage = `Error: ${error.error.message}`;
} else {
//server error
//console.log("Server Error: " + JSON.stringify(error));
if (error.status === 400){
switch (error.error.message) {
case "Invalid refresh token!":
console.log(error);
if (error?.status === 400) {
switch (error?.error?.message) {
case 'Invalid refresh token!':
this.authService.logout();
errorMessage = "Die aktuelle Sitzung ist abgelaufen. Bitte loggen sie sich erneut ein."
this.router.navigate(["/login"], { queryParams: { returnUrl: this.router.routerState.snapshot.url } });
errorMessage =
'Die aktuelle Sitzung ist abgelaufen. Bitte loggen sie sich erneut ein.';
this.router.navigate(['/login'], {
queryParams: {
returnUrl: this.router.routerState.snapshot.url,
},
});
break;
default:
errorMessage = this.serverErrorMessageGenerator(error);
errorMessage = getErrorMessage(error);
break;
}
} else if (error.status === 401) {
var urlSplit : string[] = error.url.split("/");
if (urlSplit[3] === "users" && urlSplit[5] === "update"){ // Allow user pw updates to be processed correctly
errorMessage = "Das aktuelle Passwort ist inkorrekt.";
} else if (error?.status === 401) {
var urlSplit: string[] = error.url.split('/'); //TODO: UFF might lead to bug when deployed under sub path .../frontend/...
if (urlSplit[3] === 'users' && urlSplit[5] === 'update') {
// Allow user pw updates to be processed correctly
errorMessage = 'Das aktuelle Passwort ist inkorrekt.';
} else {
return this.handle401Error(request, next);
}
} else {
errorMessage = this.serverErrorMessageGenerator(error);
}
}
if (errorMessage === "Viele Fehler sind aufgetreten.") { // Here is the thing I ment
this.snackBar.openSnackBar(errorMessage, "Erweitert", true, error.error.errors);
} else {
this.snackBar.openSnackBar(errorMessage, "Ok", true);
errorMessage = getErrorMessage(error);
}
return throwError(errorMessage);
}));
}
private serverErrorMessageGenerator (error: HttpErrorResponse): string {
if (error.error.message === undefined){
if (error.error.errors[0].message.includes("not provided")) {
return "Nicht alle benötigten Felder wurden ausgefüllt.";
} else {
return "Viele Fehler sind aufgetreten." // If you change this you have to change it over this aswell ( I know its terrible to @ )
}
if (error?.error?.errors?.length > 1) {
this.snackBar.openSnackBar(
errorMessage,
'Erweitert',
true,
error.error.errors
);
} else {
return `${error.error.message}.`; //`${error.error.message}. Fehlercode: ${error.status}.`
this.snackBar.openSnackBar(errorMessage, 'Ok', true);
}
return throwError(errorMessage);
})
);
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
Authorization: `Bearer ${token}`,
},
});
}
@ -100,15 +106,16 @@ export class TokenInterceptor implements HttpInterceptor {
this.isRefreshing = false;
this.requestTokenSubject.next(token.request_token);
return next.handle(this.addToken(request, token.request_token));
}));
})
);
} else {
return this.requestTokenSubject.pipe(
filter(token => token != null),
filter((token) => token != null),
take(1),
switchMap(jwt => {
switchMap((jwt) => {
return next.handle(this.addToken(request, jwt));
}));
})
);
}
}
}
Loading…
Cancel
Save