简体   繁体   中英

Redirect to logout after Error on Request

I've migrate our application from angular 2 to angular 5 and also migrrate from the deprecated Http to the new HttpClient.

In the old application i had the following Http-Client to redirect from error to a specific page.

 import {Router} from "@angular/router"; import {Injectable} from "@angular/core"; import {ConnectionBackend, Http, Request, RequestOptions, RequestOptionsArgs, Response} from "@angular/http"; import {Observable} from "rxjs/Observable"; import "rxjs/add/operator/catch"; @Injectable() export class HttpService extends Http { constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private router: Router) { super(backend, defaultOptions); } request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> { return super.request(url, options) .catch(this.catchErrors()); } private catchErrors() { return (res: Response) => { if (this.isError(res)) { console.log(`Internal server error occured (${res.status} - ${res.statusText})`); this.router.navigateByUrl('/error'); } else if (this.isUnauthorized(res)) { console.log(`User is not authenticated - not logged in or the session expired? (${res.status} - ${res.statusText})`); this.router.navigateByUrl('/logout'); } else if (this.isForbidden(res)) { console.log(`User does not have necessary permissions for the resource (${res.status} - ${res.statusText}): ${res.url}`); this.router.navigateByUrl('/forbidden'); } return Observable.throw(res); }; } private isError(res: Response): boolean { return res && res.status === 500; } private isUnauthorized(res: Response): boolean { return res && res.status === 401; } private isForbidden(res: Response): boolean { return res && res.status === 403; } } 

And now I have refactored this one to a HttpInterceptor

 import {Router} from "@angular/router"; import {Injectable} from "@angular/core"; import {Observable} from "rxjs/Observable"; import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from "@angular/common/http"; @Injectable() export class HttpService implements HttpInterceptor { constructor(private router: Router) { } private catchErrors() { return (res: HttpResponse<any>) => { if (this.isError(res)) { console.log(`Internal server error occured (${res.status} - ${res.statusText})`); this.router.navigateByUrl('/error'); } else if (this.isUnauthorized(res)) { console.log(`User is not authenticated - not logged in or the session expired? (${res.status} - ${res.statusText})`); this.router.navigateByUrl('/logout'); } else if (this.isForbidden(res)) { console.log(`User does not have necessary permissions for the resource (${res.status} - ${res.statusText}): ${res.url}`); this.router.navigateByUrl('/forbidden'); } return Observable.throw(res); }; } private isError(res: HttpResponse<any>): boolean { return res && res.status === 500; } private isUnauthorized(res: HttpResponse<any>): boolean { return res && res.status === 401; } private isForbidden(res: HttpResponse<any>): boolean { return res && res.status === 403; } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req).catch(this.catchErrors()); } } 

But now the navigateByUrl has no effect and the site is even accessible.

Has someone any idea how to fix this?

you can try with this solution

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const started = Date.now();
        /**
         * Handle newly created request with updated header (if given)
         */
        return next.handle(req).do((event: HttpEvent<any>) => {
            /**
             * Sucessfull Http Response Time.
             */
            if (event instanceof HttpResponse) {
                const elapsed = Date.now() - started;
            }

        }, (err: any) => {
            /**
             * redirect to the error_handler route according to error status or error_code
             */
            if (err instanceof HttpErrorResponse) {
                switch (err.status) {
                    case 500:
                        console.log(`Internal server error occured (${err.status} - ${err.statusText})`);
                        this.router.navigateByUrl('/error');
                        break;
                    case 400:
                        console.log(`User is not authenticated  - not logged in or the session expired? (${err.status} - ${err.statusText})`);
                        this.router.navigateByUrl('/logout');
                        break;
                    case 403:
                        console.log(`User does not have necessary permissions for the resource (${err.status} - ${err.statusText}): ${err.url}`);
                        this.router.navigateByUrl('/forbidden');
                        break;
                }
            }
        });
}

You didn't get any console error message?

I would try the following code:

import {Router} from "@angular/router";
import {Injectable} from "@angular/core";
import {Observable} from "rxjs/Observable";
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from "@angular/common/http";


@Injectable()
export class HttpService implements HttpInterceptor {

  constructor(private router: Router) {
  }

  private catchErrors(httpError) {
      if (this.isError(res)) {
        console.log(`Internal server error occured (${res.status} - ${res.statusText})`);
        this.router.navigateByUrl('/error');
      } else if (this.isUnauthorized(res)) {
        console.log(`User is not authenticated  - not logged in or the session expired? (${res.status} - ${res.statusText})`);
        this.router.navigateByUrl('/logout');
      } else if (this.isForbidden(res)) {
        console.log(`User does not have necessary permissions for the resource (${res.status} - ${res.statusText}): ${res.url}`);
        this.router.navigateByUrl('/forbidden');
      }

      return Observable.throw(res);
  }

  private isError(res: HttpResponse<any>): boolean {
    return res && res.status === 500;
  }

  private isUnauthorized(res: HttpResponse<any>): boolean {
    return res && res.status === 401;
  }

  private isForbidden(res: HttpResponse<any>): boolean {
    return res && res.status === 403;
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch(httpError => this.catchErrors(httpError));
  }

}

You need to make sure that your catchErrors function is binded to your HttpService class and do a Observable.throw to return a failed Observable .

Also check the type of httpError , in Angular 6+ I'm using HttpErrorResponse but I'm not sure what type is on older versions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM