Catch 401 Exception in Angular2
Asked Answered
R

1

12

When i try to connect to an unauthorized URL i get in Chrome:

zone.js:1274 POST http://localhost:8080/rest/v1/runs 401 (Unauthorized)
core.umd.js:3462 EXCEPTION: Response with status: 401 Unauthorized for URL: http://localhost:8080/rest/v1/runs

The code of my Home Component is:

import {Component, OnInit} from '@angular/core';
import {Run} from "../_models/run";
import {Http, Response} from "@angular/http";
import {RunService} from "../_services/run.service";
import {Observable} from "rxjs";

@Component({
    moduleId: module.id,
    templateUrl: 'home.component.html'
})

export class HomeComponent implements OnInit{
    url: "http://localhost:8080/rest/v1/runs"
    username: string;
    runs: Run[];

    constructor(private http: Http, private runService: RunService) {

    }

    ngOnInit(): void {
        this.username = JSON.parse(localStorage.getItem("currentUser")).username;
        this.runService.getRuns()
            .subscribe(runs => {
                this.runs = runs;
            });
    }
}

And this component uses this service:

import { Injectable } from '@angular/core';
import {Http, Headers, Response, RequestOptions, URLSearchParams} from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'
import {AuthenticationService} from "./authentication.service";
import {Run} from "../_models/run";

@Injectable()
export class RunService {
    url = "http://localhost:8080/rest/v1/runs";
    private token: string;

    constructor(private http: Http, private authenticationService: AuthenticationService) {

    }

    getRuns(): Observable<Run[]> {
        return this.http.post(this.url, JSON.stringify({ token: this.authenticationService.token }))
            .map((response: Response) => {
                console.log(response.status);
                if (response.status == 401) {
                    console.log("NOT AUTHORIZED");
                }

                let runs = response.json();
                console.log(runs);
                return runs;
            });
    }
}

What is the correct way to catch this 401 Exception and where should i do this? In the component or in the service? The final goal is to redirect to the Login page if any 401 response happens.

Rugging answered 5/10, 2016 at 10:0 Comment(0)
E
36

You will most likely want to throw an error from your RunService that can be caught in your component which can do the routing to the log in page. The code below should help you out:

In RunService:

Need to import the catch operator from rxjs:

import 'rxjs/add/operator/catch';

And your getRuns() function should change to

getRuns(): Observable<Run[]> {
    return this.http.post(this.url, JSON.stringify({ token: this.authenticationService.token }))
        .map((response: Response) => {
            let runs = response.json();
            return runs;
        })
        .catch(e => {
            if (e.status === 401) {
                return Observable.throw('Unauthorized');
            }
            // do any other checking for statuses here
        });

and then the ngOnInit in the component will be:

ngOnInit(): void {
    this.username = JSON.parse(localStorage.getItem("currentUser")).username;
    this.runService.getRuns()
        .subscribe(runs => {
            this.runs = runs;
        }, (err) => {
            if (err === 'Unauthorized') { this.router.navigateByUrl('/login');
        });
}

Obviously you'll want to cater the code to your own needs and change it about if need be but the process of catching the error from Http, throwing an Observable error and using the err callback to handle the error in your component should solve your issue.

Energumen answered 5/10, 2016 at 15:31 Comment(5)
Thanks its working fine, I have upvoted your answer and edited too. again a bunch of thanksGadwall
Thanks for this is it possible to add a service which checks all other requests and redirrdect accordingly instead of duplicating for every requestEthanethane
Yep you could do that - just create a service that imports the Router, make a function like handleRequestErrors(err) and write the code for your custom redirection there. Then wherever you want to do that you can use the service instead, something like (err) => { this.errorHandler.handleRequestErrors(err); }Energumen
@Energumen that should go into your answer as it is essential to avoid duplicate code. Helped me a lot! ThanksVachell
I get status = 0 with 401, why?Cuvette

© 2022 - 2024 — McMap. All rights reserved.