Пытаюсь перехватить 401 в http-перехватчике, обновляю свой сеанс и повторяю исходный запрос

#angular #typescript

#angular #typescript

Вопрос:

Я пытаюсь перехватить ответы, возвращающиеся от /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)))
            })
        )
}
  

Есть предложения о том, как я мог бы достичь того, что я пытаюсь?

Ответ №1:

Возможно, в этом есть несколько синтаксических ошибок, потому что я пишу с мобильного, но это должно помочь вам начать

 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)
    .do((event: HttpEvent<any>) =>
        return from(this.sessionService.refresh())
               .pipe(map(() => next.handle(cloned)))
        }), (err: any) => {
             if (err instanceof HttpResponse) {
                  if(err.status === 401){
                       return throwError(error);
                  }
        }
    )
}
  

Ответ №2:

Ответ состоял в том, чтобы использовать 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)))
}