2016-04-14 16 views
6

Nel mio servizio, desidero descrivere un comportamento quando l'utente viene reindirizzato se non autorizzato.Angular2: come reindirizzare se l'API restituisce un errore?

export class MessagesService { 
    constructor (private http: Http) {} 

    private _usersUrl = '/users.json'; // URL to web api 


    getUsers() { 
     return this.http.get(this._usersUrl) 
      .map(res => <User[]> res.json().data) 
      .catch(this.handleError); 
    } 

    private handleError (error: Response) { 

     if (error.status == 401) { 
      // How do I tell Angular to navigate LoginComponent from here? 
     } else { 
      return Observable.throw(error.json().error || 'Server error'); 
     } 
    } 
} 

Le mie domande sono:

  • E 'anche possibile?
  • È una buona pratica?
    • In caso affermativo, come si esegue?
    • Se no, in quale altro modo posso farlo?
+0

Vedi http://stackoverflow.com/questions/36599523/angular-2-route-to-404-page-when-route-param-is-invalid/36609006#36609006 –

+0

@ GünterZöchbauer doesn' t risposta alla mia domanda sull'utilizzo del router in servizio – Viktor

+0

Non so perché. Se si inietta il costruttore 'router (http: Http, router privato: Router) {}' dovrebbe essere in grado di usarlo. Vedi anche il link sotto la domanda. –

risposta

9

Il mio approccio è stato quello di creare il mio servizio di richiesta e avere una funzione intercettore che avvolge la richiesta effettiva di gestire 401 e 403 ecc

hanno incluso qui sotto se si vuole avere uno sguardo esso .

import {Injectable} from "@angular/core" 
import {Subscription, Observable} from "rxjs" 
import {TokenModel} from "../../models/token.model" 
import {TokenService} from "../authentication/token.service" 
import {Http, Headers, URLSearchParams, RequestOptions, Request, RequestMethod} from "@angular/http" 
import {Router} from "@angular/router" 

@Injectable() 
export class RequestService 
{ 
    private baseUrl: string; 
    private subscription: Subscription; 
    private token: TokenModel; 

    constructor(public tokenService: TokenService, 
       public http: Http, 
       public router: Router) 
    { 
     this.baseUrl = `${process.env.API_URL}/example`; 
     this.subscription = this.tokenService.token$.subscribe(token => this.token = token); 
    } 

    get(path: string, params?: Object, withCredentials?: boolean): Observable<any> 
    { 
     this.checkAuthorised(); 

     const url: string = this.baseUrl + path; 
     const headers: Headers = new Headers({ 
      'Accept': 'application/json' 
     }); 

     const searchParams = new URLSearchParams(`user_session=${this.token.token}`); 

     for (let param in params) searchParams.set(param, params[param]); 

     const options: RequestOptions = new RequestOptions({ 
      url: url, 
      method: RequestMethod.Get, 
      headers: headers, 
      search: searchParams, 
      withCredentials: withCredentials 
     }); 

     const request = new Request(options); 

     return this.makeRequest(request); 
    } 

    post(path: string, body?: Object, params?: Object, useDataProperty?: boolean, withCredentials?: boolean): Observable<any> 
    { 
     this.checkAuthorised(); 

     const url: string = this.baseUrl + path; 

     const headers: Headers = new Headers({ 
      'Accept': 'application/json', 
      'Content-Type': 'application/json', 
     }); 

     const data = JSON.stringify(useDataProperty ? {data: body} : body); 

     const searchParams = new URLSearchParams(`user_session=${this.token.token}`); 

     for (let param in params) searchParams.set(param, params[param]); 

     const options: RequestOptions = new RequestOptions({ 
      url: url, 
      method: RequestMethod.Post, 
      headers: headers, 
      body: data, 
      search: searchParams, 
      withCredentials: withCredentials 
     }); 

     const request = new Request(options); 

     return this.makeRequest(request); 
    } 

    makeRequest(request: Request) 
    { 
     return this.intercept(this.http.request(request).map(res => res.json())); 
    } 

    intercept(observable: Observable<any>) 
    { 
     return observable.catch(err => 
     { 

      if (err.status === 401) 
      { 
       return this.unauthorised(); 

      } else if (err.status === 403) 
      { 
       return this.forbidden(); 
      } else 
      { 
       return Observable.throw(err); 
      } 
     }); 
    } 

    unauthorised(): Observable<any> 
    { 
     this.tokenService.clear(); 
     this.router.navigate(['/login']); 
     return Observable.empty(); 
    } 

    forbidden(): Observable<any> 
    { 
     this.router.navigate(['/']); 
     return Observable.empty(); 
    } 

    checkAuthorised(): void 
    { 
     if (!this.token.token.length) 
     { 
      this.router.navigate(['login']); 
     } 
    } 


} 
+0

Non penso che pubblicare un link sia una buona idea. Il tuo elenco può essere rimosso un giorno. Penso che sia meglio pubblicare il tuo codice qui. – Viktor

0

Una direzione stiamo avvicinando questo sul nostro team è implementando una classe client API. Questo client API avvolge il servizio Http originale.

L'idea è che, poiché il servizio HTTP produce osservabili si può facilmente estendere il suo comportamento da parte degli operatori aggiungendo come map, flatMap e catch operatori al osservabile originale prodotta dal servizio HTTP.

Penso che troverai questo esempio un utile punto di partenza per risolvere il problema che stai riscontrando.

import { ApiRequestOptions } from './api-request-options.service'; 
import { Http, Response, RequestOptions, ResponseContentType } from '@angular/http'; 

import 'rxjs/add/observable/zip'; 
import 'rxjs/add/operator/map'; 
import { Observable } from 'rxjs/Rx'; 
import { Injectable } from '@angular/core'; 
import { Router } from '@angular/router'; 

@Injectable() 
export class ApiClient { 
    // PLease note, the API request options service is a helper that we introduced 
    // to generate absolute URLs based on settings in the client. 
    // I did not include it here for brevity. 
    constructor(private router: Router, private http: Http, private requestOptions: ApiRequestOptions) { 

    } 

    get<TResponse>(path: string, queryStringParams?: any): Observable<TResponse> { 
     let self = this; 

     return Observable.zip(
      this.requestOptions.absoluteUrlFor(path, queryStringParams), 
      this.requestOptions.authorizedRequestOptions() 
     ).flatMap(requestOpts => { 
      let [url, options] = requestOpts; 
      return self.http.get(url, options); 
     }).catch(response => { 
      if (response.status === 401) { 
       self.router.navigate(['/login']); 
      } 

      return response; 
     }).map((response: Response) => <TResponse>response.json()); 
    } 

    post<TResponse>(path: string, body: any): Observable<TResponse> { 
     let self = this; 

     return Observable.zip(
      this.requestOptions.absoluteUrlFor(path), 
      this.requestOptions.authorizedRequestOptions() 
     ).flatMap(requestOpts => { 
      let [url, options] = requestOpts; 
      return self.http.post(url, body, options); 
     }).catch(response => { 
      if (response.status === 401) { 
       self.router.navigate(['/login']); 
      } 

      return response; 
     }).map((response: Response) => <TResponse>response.json()); 
    } 

    put<TResponse>(path: string, body: any): Observable<TResponse> { 
     let self = this; 

     return Observable.zip(
      this.requestOptions.absoluteUrlFor(path), 
      this.requestOptions.authorizedRequestOptions() 
     ).flatMap(requestOpts => { 
      let [url, options] = requestOpts; 
      return self.http.put(url, body, options); 
     }).catch(response => { 
      if (response.status === 401) { 
       self.router.navigate(['/login']); 
      } 

      return response; 
     }).map((response: Response) => { 
      if (response.status === 200) { 
       return <TResponse>response.json(); 
      } else { 
       return null; 
      } 
     }); 
    } 

    delete(path: string): Observable<Response> { 
     let self = this; 

     return Observable.zip(
      this.requestOptions.absoluteUrlFor(path), 
      this.requestOptions.authorizedRequestOptions() 
     ).flatMap(requestOpts => { 
      let [url, options] = requestOpts; 
      return self.http.delete(url, options); 
     }).catch(response => { 
      if (response.status === 401) { 
       self.router.navigate(['/login']); 
      } 

      return response; 
     }); 
    } 
}