11

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.

ManfredP
  • 1,037
  • 1
  • 12
  • 27

1 Answers1

35

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.

peppermcknight
  • 1,545
  • 16
  • 30
  • Thanks its working fine, I have upvoted your answer and edited too. again a bunch of thanks – Neeraj Rathod Dec 28 '16 at 06:40
  • Thanks for this is it possible to add a service which checks all other requests and redirrdect accordingly instead of duplicating for every request – Geoff Jan 26 '17 at 20:49
  • 3
    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); }` – peppermcknight Feb 02 '17 at 15:42
  • 1
    @peppermcknight that should go into your answer as it is essential to avoid duplicate code. Helped me a lot! Thanks – Max Feb 24 '17 at 12:51
  • 1
    I get status = 0 with 401, why? – stackdave Jun 26 '17 at 20:15