next.handle(request) 在多个 HTTP 拦截器中失败:未定义



在一个项目中,我使用 2 个 HTTP 拦截器:1 个为每个请求添加一个 JWT 令牌,另一个用于拦截传入的 401 错误状态。

我调用一个单独的程序来获取此服务中我的应用的所有反馈:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '@environments/environment';
import { Feedback } from '@app/_models/feedback';
@Injectable({ providedIn: 'root' })
export class FeedbackService {
constructor(
private http: HttpClient
) {}
getAll() {
return this.http.get<Feedback[]>(`${environment.apiUrl}/feedback`);
}
getById(id: string) {
return this.http.get<Feedback>(`${environment.apiUrl}/feedback/${id}`);
}
delete(id: string) {
return this.http.delete(`${environment.apiUrl}/feedback/${id}`);
}
}

JWT 拦截器:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '@environments/environment';
import { AuthorizationService } from 'src/shared/authorization.service';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private auth: AuthorizationService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add auth header with jwt if user is logged in and request is to the api url
const authenticatedUser = this.auth.getAuthenticatedUser();
if (authenticatedUser == null) {
return;
}
authenticatedUser.getSession( (err, session) => {
if (err) {
console.log(err);
return;
}
const isApiUrl = request.url.startsWith(environment.apiUrl);
const token = session.getIdToken().getJwtToken();
const headers = new Headers();
headers.append('Authorization', token);
if (this.auth.isLoggedIn() && isApiUrl) {
request = request.clone({
setHeaders: {
Authorization: token,
}
});
}
return next.handle(request);
});
}
}

错误拦截器:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { AccountService } from '@app/_services';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private accountService: AccountService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log(next.handle(request));
return next.handle(request).pipe(catchError(err => {
if (err.status === 401) {
// auto logout if 401 response returned from api
this.accountService.logout();
}
const error = err.error.message || err.statusText;
return throwError(error);
}));
}
}

当我在我的应用程序模块中提供两个拦截器时,

{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },

我总是收到以下错误。发生这种情况是因为next.handle(request)显然是undefined,我真的不知道为什么。仅使用错误拦截器没有问题。

ERROR TypeError: Cannot read property 'pipe' of undefined
at ErrorInterceptor.intercept (error.interceptor.ts:14)
at HttpInterceptorHandler.handle (http.js:1958)
at HttpXsrfInterceptor.intercept (http.js:2819)
at HttpInterceptorHandler.handle (http.js:1958)
at HttpInterceptingHandler.handle (http.js:2895)
at MergeMapSubscriber.project (http.js:1682)
at MergeMapSubscriber._tryNext (mergeMap.js:46)
at MergeMapSubscriber._next (mergeMap.js:36)
at MergeMapSubscriber.next (Subscriber.js:49)
at Observable._subscribe (subscribeToArray.js:3)

仅使用 JwtInterceptor 会给出以下错误,我无法弄清楚它来自哪里。当然,我想同时使用两者。我在配置多个拦截器时是否遗漏了什么?

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:27)
at subscribeToResult (subscribeToResult.js:11)
at MergeMapSubscriber._innerSub (mergeMap.js:59)
at MergeMapSubscriber._tryNext (mergeMap.js:53)
at MergeMapSubscriber._next (mergeMap.js:36)
at MergeMapSubscriber.next (Subscriber.js:49)
at Observable._subscribe (subscribeToArray.js:3)
at Observable._trySubscribe (Observable.js:42)
at Observable.subscribe (Observable.js:28)
at MergeMapOperator.call (mergeMap.js:21)

重写你的 JwtInterceptor:

import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, from } from 'rxjs';
import { environment } from '@environments/environment';
import { AuthorizationService } from 'src/shared/authorization.service';

@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private auth: AuthorizationService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.getSessionWithAuthReq(request, next));
}
async getSessionWithAuthReq(request: HttpRequest<any>, next: HttpHandler){
const authenticatedUser = this.auth.getAuthenticatedUser();

if (authenticatedUser) {
const authRequest:  HttpRequest<any>  = await new Promise( (resolve) => {
authenticatedUser.getSession( (err, session) => {
if (err) {
console.log(err);
// want to go on without authenticating if there is an error from getting session 
return resolve(request);
}
const isApiUrl = request.url.startsWith(environment.apiUrl);
const token = session.getIdToken().getJwtToken();
const headers = new Headers();
headers.append('Authorization', token);
if (this.auth.isLoggedIn() && isApiUrl) {
const req = request.clone({
setHeaders: {
Authorization: token,
}
});
return resolve(req);
}
return resolve(request);
});
});


return next.handle(authRequest).toPromise();
}
return next.handle(request).toPromise();
}
}

最新更新