Angular handle for 500 server errors

skydev picture skydev · Oct 2, 2018 · Viewed 17.2k times · Source

How can I modify my http call to handle(catch) for 500 server errors. I try calling an API but receive a '500 (Internal server error' in the 'err' part of the function. I would like to be able to catch it if possible but am not sure how. Is there a simple way to do this?

  call_http() {
    this.http.get<any>('/api/goes/here').subscribe(data => {
      this.result = data;
    },
      err => {
        console.log(err);
      });
  }

I am not using any headers, map, errorhandler etc. This is just a basic call.

Answer

codeepic picture codeepic · Oct 2, 2018

If you want to intercept errors when using HttpClient service to make backend calls and don't repeat yourself in every call you make, you need to use interceptor.

This is what we use in our application and depending on the type of error: 500, 400, 404, 403, we redirect, show payment modal or just show toast message:

Http status error codes:

export class HttpError{
    static BadRequest = 400;
    static Unauthorized = 401;
    static Forbidden = 403;
    static NotFound = 404;
    static TimeOut = 408;
    static Conflict = 409;
    static InternalServerError = 500;
}

Interceptor code:

import {Injectable, Injector} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http'
import {Observable} from 'rxjs/Observable';
import {AuthorizationService} from "../authorization.service/authorization.service";
import {HttpError} from "./http-error";
import {Router} from "@angular/router";
import {Toaster} from "nw-style-guide/toasts";

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
// Regular dep. injection doesn't work in HttpInterceptor due to a framework issue (as of [email protected]),
// use Injector directly (don't forget to add @Injectable() decorator to class).
constructor(private _injector: Injector) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const logFormat = 'background: maroon; color: white';

    return next.handle(req)
        .do(event => {
        }, exception => {
            if (exception instanceof HttpErrorResponse) {
                switch (exception.status) {

                    case HttpError.BadRequest:
                        console.error('%c Bad Request 400', logFormat);
                        break;

                    case HttpError.Unauthorized:
                        console.error('%c Unauthorized 401', logFormat);
                        window.location.href = '/login' + window.location.hash;
                        break;

                    case HttpError.NotFound:
                        //show error toast message
                        console.error('%c Not Found 404', logFormat);
                        const _toaster = this._injector.get(Toaster),
                            _router = this._injector.get(Router);
                        _toaster.show({
                            message: exception.error && exception.error.message ? exception.error.message :
                                exception.statusText,
                            typeId: 'error',
                            isDismissable: true
                        });
                        _router.navigate(['']);
                        break;

                    case HttpError.TimeOut:
                        // Handled in AnalyticsExceptionHandler
                        console.error('%c TimeOut 408', logFormat);
                        break;

                    case HttpError.Forbidden:
                        console.error('%c Forbidden 403', logFormat);
                        const _authService = this._injector.get(AuthorizationService);
                        _authService.showForbiddenModal();
                        break;

                    case HttpError.InternalServerError:
                        console.error('%c big bad 500', logFormat);
                        break;
                }
            }
        });
}

}

You also need to add the interceptor into @NgModule providers where you bootstrap your app:

    {
        provide: HTTP_INTERCEPTORS,
        useClass: ErrorInterceptor,
        multi: true
    },

Modify the code according to your needs - when started - we were just logging things to the console. Once you have this interceptor in place, it will handle all backend requests that go though HttpClient service.