我喜欢拥有一个HttpInterceptor(角度6),它添加了授权标头,但也处理401以重定向到登录页面。 这是我的代码:
import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs';
import {Router} from '@angular/router';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private router: Router) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
},
});
}
const req = next.handle(request);
// ---------------- VVV ---------------
req.subscribe(() => {
}, (error: any) => {
if (error instanceof HttpErrorResponse && (error as HttpErrorResponse).status === 401)
this.router.navigate(['public/login']);
});
// ---------------- ^^^ ---------------
return req;
}
}
一切正常,因为vvv / ^^^注释中的代码强制将请求发送两次。为什么这个?好的,我可能必须订阅请求,因为此拦截器进行了订阅,并且可能使用了HttpClient服务。 有没有解决此问题的方法?
编辑:这是package.json中的依赖项:
...
"@angular/compiler": "6.0.3",
"@angular/core": "6.0.3",
"@angular/http": "6.0.3",
"@angular/router": "6.0.3",
"rxjs": "^6.2.0",
"rxjs-compat": "^6.2.0",
"rxjs-tslint": "^0.1.4",
"zone.js": "^0.8.26"
...
答案 0 :(得分:1)
您应该使用do()
而不是subscribe()
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
},
});
}
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
}, (err: any) => {
if (err instanceof HttpErrorResponse {
if (err.status === 401) {
this.router.navigate(['public/login']);
}
}
});
}
Difference between do() and subscribe()
修改
导入do
运算符import { do } from 'rxjs/operators';
为什么用作订阅时忽略/点击?
这里的要点是do()
不会影响流的流,这与其他运算符不同。它接受响应,执行某些操作,即使它修改了响应,流也将忽略它。当您尝试将其用作subscribe()
时,它会被忽略,因为您已经在下面的语句中返回了流
答案 1 :(得分:0)
安装 rxjs-compat ,然后尝试一下,它对我有用。
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpEvent,
HttpResponse,
HttpErrorResponse
} from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { do } from 'rxjs/operators';
@Injectable()
export class InterceptorService implements HttpInterceptor {
constructor(private router: Router) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (
localStorage.getItem('JWT-TOKE') !== '' &&
localStorage.getItem('JWT-TOKE') !== null
) {
const JWT = localStorage.getItem('JWT-TOKE');
req = req.clone({
setHeaders: {
Authorization: 'Bearer ' + JWT
}
});
}
return next.handle(req).do(
(event: HttpEvent<any>) => {},
(err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
localStorage.clear();
this.router.navigate(['/login']);
}
}
}
);
}
}
更新
如果您不使用 rxjs-compat ,则使用tap代替do,因为 do 是javascript中的保留关键字。
import { Injectable } from "@angular/core";
import {
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpEvent,
HttpResponse,
HttpErrorResponse
} from "@angular/common/http";
import { Router } from "@angular/router";
import { Observable } from "rxjs";
import { tap } from "rxjs/operators";
import "rxjs/add/operator/do";
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
constructor(private router: Router) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (
localStorage.getItem("jwtToken") !== "" &&
localStorage.getItem("jwtToken") !== null
) {
const JWT = localStorage.getItem("jwtToken");
req = req.clone({
setHeaders: {
Authorization: JWT
}
});
}
return next.handle(req).pipe(
tap((event: HttpEvent<any>) => {
console.log(event);
// handle error here
}),
tap((err: any) => {
console.log(err);
})
);
}
}