admin管理员组

文章数量:1026989

In a project, I work with 2 HTTP interceptors: 1 to add a JWT token to each request, the other to intercept an ining 401 error status.

I call a separate program to get all feedback for my app in this service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/mon/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}`);
    }
}

The JWT interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        });
    }
}

The Error interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        }));
    }
}

When I provide both interceptors in my app.module,

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

I always get an error saying the following below. This happens because next.handle(request) apparently is undefined, and I don't really know why. Using only the Error interceptor works with no issue.

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)

Using only the JwtInterceptor gives following error, which I can't figure out where it's ing from. Of course, I would want to use both. Am I missing something while configuring the multiple interceptors?

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)

In a project, I work with 2 HTTP interceptors: 1 to add a JWT token to each request, the other to intercept an ining 401 error status.

I call a separate program to get all feedback for my app in this service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/mon/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}`);
    }
}

The JWT interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        });
    }
}

The Error interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        }));
    }
}

When I provide both interceptors in my app.module,

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

I always get an error saying the following below. This happens because next.handle(request) apparently is undefined, and I don't really know why. Using only the Error interceptor works with no issue.

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)

Using only the JwtInterceptor gives following error, which I can't figure out where it's ing from. Of course, I would want to use both. Am I missing something while configuring the multiple interceptors?

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)
Share Improve this question asked Jun 29, 2020 at 10:12 JasperRJasperR 3692 gold badges6 silver badges17 bronze badges 1
  • JwtInterceptor.intercept() doesn't always return an Observable. – martin Commented Jun 29, 2020 at 12:11
Add a ment  | 

1 Answer 1

Reset to default 1

Rewrite your JwtInterceptor:

import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from '@angular/mon/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();
    }
}

In a project, I work with 2 HTTP interceptors: 1 to add a JWT token to each request, the other to intercept an ining 401 error status.

I call a separate program to get all feedback for my app in this service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/mon/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}`);
    }
}

The JWT interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        });
    }
}

The Error interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        }));
    }
}

When I provide both interceptors in my app.module,

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

I always get an error saying the following below. This happens because next.handle(request) apparently is undefined, and I don't really know why. Using only the Error interceptor works with no issue.

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)

Using only the JwtInterceptor gives following error, which I can't figure out where it's ing from. Of course, I would want to use both. Am I missing something while configuring the multiple interceptors?

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)

In a project, I work with 2 HTTP interceptors: 1 to add a JWT token to each request, the other to intercept an ining 401 error status.

I call a separate program to get all feedback for my app in this service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/mon/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}`);
    }
}

The JWT interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        });
    }
}

The Error interceptor:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/mon/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);
        }));
    }
}

When I provide both interceptors in my app.module,

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

I always get an error saying the following below. This happens because next.handle(request) apparently is undefined, and I don't really know why. Using only the Error interceptor works with no issue.

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)

Using only the JwtInterceptor gives following error, which I can't figure out where it's ing from. Of course, I would want to use both. Am I missing something while configuring the multiple interceptors?

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)
Share Improve this question asked Jun 29, 2020 at 10:12 JasperRJasperR 3692 gold badges6 silver badges17 bronze badges 1
  • JwtInterceptor.intercept() doesn't always return an Observable. – martin Commented Jun 29, 2020 at 12:11
Add a ment  | 

1 Answer 1

Reset to default 1

Rewrite your JwtInterceptor:

import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from '@angular/mon/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();
    }
}

本文标签: javascriptnexthandle(request) in multiple HTTP interceptors fails undefinedStack Overflow