Dans mon projet Angular 2, je fais des appels API à partir de services qui renvoient un Observable. L'indicatif d'appel souscrit alors à cet observable. Par exemple:
getCampaigns(): Observable<Campaign[]> {
return this.http.get('/campaigns').map(res => res.json());
}
Disons que le serveur renvoie un 401. Comment puis-je intercepter globalement cette erreur et rediriger vers une page / un composant de connexion?
Merci.
Voici ce que j'ai jusqu'à présent:
// boot.ts
import {Http, XHRBackend, RequestOptions} from 'angular2/http';
import {CustomHttp} from './customhttp';
bootstrap(AppComponent, [HTTP_PROVIDERS, ROUTER_PROVIDERS,
new Provider(Http, {
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
deps: [XHRBackend, RequestOptions]
})
]);
// customhttp.ts
import {Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
@Injectable()
export class CustomHttp extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
console.log('request...');
return super.request(url, options);
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
console.log('get...');
return super.get(url, options);
}
}
Le message d'erreur que j'obtiens est "backend.createConnection n'est pas une fonction"
Réponses:
La description
La meilleure solution que j'ai trouvée est de remplacer le
XHRBackend
tel que l'état de la réponse HTTP401
et403
conduit à une action particulière.Si vous gérez votre authentification en dehors de votre application Angular, vous pouvez forcer une actualisation de la page actuelle de sorte que votre mécanisme externe se déclenche. Je détaille cette solution dans l'implémentation ci-dessous.
Vous pouvez également transférer vers un composant de votre application afin que votre application Angular ne soit pas rechargée.
la mise en oeuvre
Angulaire> 2,3,0
Grâce à @mrgoos, voici une solution simplifiée pour angular 2.3.0+ en raison d'un bug corrigé dans angular 2.3.0 (voir issue https://github.com/angular/angular/issues/11606 ) étendant directement le
Http
module.Le fichier de module contient désormais uniquement le fournisseur suivant.
Une autre solution utilisant Router et un service d'authentification externe est détaillée dans l' essentiel suivant par @mrgoos.
Angulaire pré-2.3.0
L'implémentation suivante fonctionne pour
Angular 2.2.x FINAL
etRxJS 5.0.0-beta.12
.Il redirige vers la page actuelle (plus un paramètre pour obtenir une URL unique et éviter la mise en cache) si un code HTTP 401 ou 403 est renvoyé.
avec le fichier de module suivant.
la source
catch()
pas été trouvée. (smh)import "rxjs/add/operator/catch";
http
? Le seul avantage que je vois est que vous pouvez simplement le mettre en tant que fournisseur:{ provide: XHRBackend, useClass: AuthenticationConnectionBackend }
alors que lorsque vous surchargez Http, vous devez écrire du code plus gênantuseFactory
et vous limiter en appelant `` nouveau '' et en envoyant des arguments spécifiques. WDYT? Une référence à la 2ème méthode: adonespitogo.com/articles/angular-2-extending-http-providerAngulaire 4.3+
Avec l'introduction de HttpClient est venu la possibilité d'intercepter facilement toutes les demandes / réponses. L'utilisation générale de HttpInterceptors est bien documentée , voyez l'utilisation de base et comment fournir l'intercepteur. Voici un exemple d'un HttpInterceptor qui peut gérer les erreurs 401.
Mis à jour pour RxJS 6+
RxJS <6
la source
Router
ici ne semble pas fonctionner. Par exemple, je souhaite diriger mes utilisateurs vers la page de connexion lorsqu'ils obtiennent un 401-403, mais celathis.router.navigate(['/login']
ne fonctionne pas pour moi. Ça ne fait rienimport 'rxjs/add/operator/do';
après avoir importé rxjs.Comme les API frontales expirent plus rapidement que le lait, avec Angular 6+ et RxJS 5.5+, vous devez utiliser
pipe
:Mise à jour pour Angular 7+ et rxjs 6+
la source
error TS2322: Type 'Observable<{}>' is not assignable to type 'Observable<HttpEvent<any>>'.
quand le.pipe
est là-dedans, aucune erreur lorsque je supprime le.pipe
req
est en faitrequest
- la modification estLe que
Observable
vous obtenez de chaque méthode de requête est de typeObservable<Response>
. L'Response
objet a unestatus
propriété qui contiendra le401
SI le serveur a renvoyé ce code. Vous voudrez peut-être le récupérer avant de le mapper ou de le convertir.Si vous voulez éviter de faire cette fonctionnalité à chaque appel, vous devrez peut-être étendre la
Http
classe d' Angular 2 et injecter votre propre implémentation qui appelle le parent (super
) pour laHttp
fonctionnalité normale , puis gérer l'401
erreur avant de renvoyer l'objet.Voir:
https://angular.io/docs/ts/latest/api/http/index/Response-class.html
la source
Angulaire 4.3+
Pour compléter la réponse de la dague de Gilbert Arenas :
Si vous avez besoin d'intercepter une erreur, de lui appliquer un traitement et de la transmettre le long de la chaîne (et pas seulement d'ajouter un effet secondaire avec
.do
), vous pouvez utiliser HttpClient et ses intercepteurs pour faire quelque chose du genre:la source
Pour éviter le problème de référencement cyclique causé par l'injection de services tels que "Router" dans une classe dérivée Http, il faut utiliser la méthode Injector post-constructeur. Le code suivant est une implémentation fonctionnelle d'un service Http qui redirige vers la route de connexion chaque fois qu'une API REST renvoie «Token_Expired». Notez qu'il peut être utilisé comme une substitution au Http normal et, en tant que tel, ne nécessite aucune modification des composants ou services déjà existants de votre application.
app.module.ts
Extended-http.service.ts
la source
À partir de Angular> = 2.3.0, vous pouvez remplacer le
HTTP
module et injecter vos services. Avant la version 2.3.0, vous ne pouviez pas utiliser vos services injectés en raison d'un bogue principal.J'ai créé un résumé pour montrer comment c'est fait.
la source
app.module
code? Merci.HTTP
ailleurs?Angular> 4.3: ErrorHandler pour le service de base
la source