首页 > 解决方案 > 试图在 http 拦截器中捕获 401,刷新我的会话并重试原始请求

问题描述

我正在尝试拦截来自 的响应/api,如果它们是 401,则捕获它们,执行刷新会话操作,然后再次重试原始 HTTP 调用(另外,如果它再次出现 401,则防止它无限循环)

我认为我在下面的代码中正在做的是使用 http 处理程序触发请求,订阅其事件,如果它在 401 上失败,则刷新然后返回一个可观察的克隆请求正在被处理程序操作。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (!request.url.startsWith('/api')) {
        return next.handle(request)
    }

    const cloned = request.clone()
    return next.handle(request)
        .pipe(
            catchError((error: any) => {
                if (error.status !== 401) {
                    return throwError(error)
                }
                return from(this.sessionService.refresh())
                    .pipe(map(() => next.handle(cloned)))
            })
        )
}

关于如何实现我想要的目标的任何建议?

标签: angulartypescript

解决方案


答案是使用switctMap而不是map

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
{
    if (!request.url.startsWith('/api')) {
        return next.handle(request)
    }

    const cloned = request.clone()
    return next.handle(request)
        .pipe(
            catchError((error: any) => {
                if (error.status !== 401) {
                    return throwError(error)
                }
                return from(this.sessionService.refresh())
                    .pipe(switchMap(() => next.handle(cloned)))
        })
    )
}

但是,我选择了另一种方法,在请求发生之前检查我是否有会话,如果需要,注入刷新操作。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (
        !request.url.startsWith('/api') || 
        this.sessionService.isValid
    ) {
        return next.handle(request)
    }

    return from(this.sessionService.refresh())
        .pipe(switchMap(() => next.handle(request)))
}

推荐阅读