| /******************************************************************************** |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ********************************************************************************/ |
| import { Injectable } from '@angular/core'; |
| import { TranslateService } from '@ngx-translate/core'; |
| import { NotificationsService } from 'angular2-notifications'; |
| import { Router } from '@angular/router'; |
| import { Observable } from 'rxjs'; |
| import { ConfigService } from 'app/app-config.service'; |
| |
| @Injectable() |
| export class HttpResponseHandler { |
| constructor( |
| private router: Router, |
| private translateService: TranslateService, |
| private notificationsService: NotificationsService, |
| private configService: ConfigService |
| ) {} |
| |
| /** |
| * Global http error handler. |
| * |
| * @param error |
| * @param source |
| * @returns {ErrorObservable} |
| */ |
| public onCatch(response: any, source: Observable<any>): Observable<any> { |
| switch (response.status) { |
| case 400: |
| this.handleBadRequest(response); |
| break; |
| |
| case 401: |
| this.handleUnauthorized(response); |
| break; |
| |
| case 403: |
| this.handleForbidden(); |
| break; |
| |
| case 404: |
| this.handleNotFound(response); |
| break; |
| |
| case 409: |
| this.handleRefExists(); |
| break; |
| |
| case 500: |
| this.handleServerError(); |
| break; |
| |
| default: |
| break; |
| } |
| |
| return Observable.throw(response); |
| } |
| |
| /** |
| * Shows notification errors when server response status is 401 |
| * |
| * @param error |
| */ |
| private handleBadRequest(responseBody: any): void { |
| if (responseBody._body) { |
| try { |
| const bodyParsed = responseBody.json(); |
| this.handleErrorMessages(bodyParsed); |
| } catch (error) { |
| this.handleServerError(); |
| } |
| } else { |
| this.handleServerError(); |
| } |
| } |
| |
| /** |
| * Shows notification errors when server response status is 401 and redirects user to login page |
| * |
| * @param responseBody |
| */ |
| private handleUnauthorized(responseBody: any): void { |
| // Read configuration in order to see if we need to display 401 notification message |
| let unauthorizedEndpoints: Array<string> = this.configService.get('notifications').unauthorizedEndpoints; |
| |
| unauthorizedEndpoints = unauthorizedEndpoints.filter(endpoint => this.getRelativeUrl(responseBody.url) === endpoint); |
| this.router.navigate(['/login']); |
| |
| if (unauthorizedEndpoints.length) { |
| this.notificationsService.info('Info', this.translateService.instant('ServerError401'), this.configService.get('notifications').options); |
| } |
| } |
| |
| /** |
| * Shows notification errors when server response status is 403 |
| */ |
| private handleForbidden(): void { |
| this.notificationsService.error('error', this.translateService.instant('ServerError403'), this.configService.get('notifications').options); |
| this.router.navigate(['/login']); |
| } |
| |
| /** |
| * Shows notification errors when server response status is 404 |
| * |
| * @param responseBody |
| */ |
| private handleNotFound(responseBody: any): void { |
| // Read configuration in order to see if we need to display 401 notification message |
| const message: any = this.translateService.instant('ServerError404'), |
| title = this.translateService.instant('ErrorNotificationTitle'); |
| |
| this.showNotificationError(title, message); |
| } |
| |
| /** |
| * Shows notification errors when server response status is 409 |
| */ |
| private handleRefExists(): void { |
| const message: any = this.translateService.instant('ServerError409'), |
| title = this.translateService.instant('ErrorNotificationTitle'); |
| |
| this.showNotificationError(title, message); |
| } |
| |
| /** |
| * Shows notification errors when server response status is 500 |
| */ |
| private handleServerError(): void { |
| const message = this.translateService.instant('ServerError500'), |
| title = this.translateService.instant('ErrorNotificationTitle'); |
| |
| this.showNotificationError(title, message); |
| } |
| |
| /** |
| * Parses server response and shows notification errors with translated messages |
| * |
| * @param response |
| */ |
| private handleErrorMessages(response: any): void { |
| if (!response) { |
| return; |
| } |
| |
| for (const key of Object.keys(response)) { |
| if (Array.isArray(response[key])) { |
| response[key].forEach(value => this.showNotificationError('Error', this.getTranslatedValue(value))); |
| } else { |
| this.showNotificationError('Error', this.getTranslatedValue(response[key])); |
| } |
| } |
| } |
| |
| /** |
| * Extracts and returns translated value from server response |
| * |
| * @param value |
| * @returns {string} |
| */ |
| private getTranslatedValue(value: string): string { |
| if (value.indexOf('[') > -1) { |
| const key = value.substring(value.lastIndexOf('[') + 1, value.lastIndexOf(']')); |
| value = this.translateService.instant(key); |
| } |
| |
| return value; |
| } |
| |
| /** |
| * Returns relative url from the absolute path |
| * |
| * @param responseBody |
| * @returns {string} |
| */ |
| private getRelativeUrl(url: string): string { |
| return url.toLowerCase().replace(/^(?:\/\/|[^\/]+)*\//, ''); |
| } |
| |
| /** |
| * Shows error notification with given title and message |
| * |
| * @param title |
| * @param message |
| */ |
| private showNotificationError(title: string, message: string): void { |
| this.notificationsService.error(title, message, this.configService.get('notifications').options); |
| } |
| } |