首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >角形自动重发失败的http请求3次-为什么?

角形自动重发失败的http请求3次-为什么?
EN

Stack Overflow用户
提问于 2019-07-23 10:35:15
回答 1查看 774关注 0票数 0

看来这可能是我的错,但我想不出原因。每当我使用HttpClient postget在我的应用程序中的任何地方发送HTTP请求并接收到非2xx响应时,请求都会立即重试3次(总共4次)。我不想要这种行为,如果不想的话,我就想把它关掉。

如果我用管道将retry输送到我可观察到的管道中,我就会想到这种行为,但我没有。我确实安装了一些拦截器,以便进行auth和错误处理,但我看不到会导致这种行为的任何东西。有人能提出一个方法来追踪导致这些重试的原因吗?

编辑:原来这肯定是由我的auth拦截器造成的。

代码语言:javascript
运行
复制
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
import { throwError, Observable, BehaviorSubject, of, from } from 'rxjs';
import { catchError, filter, take, switchMap, finalize } from 'rxjs/operators';
import { AuthService } from './auth.service';
import { environment } from 'src/environments/environment';

/**
 * Disables this interceptor for a given HTTP request
 * Usage: this.http.get(`${environment.apiBase}someEndpoint`, { headers: new HttpHeaders().set(SkipAuthorizationHeader, '') })
 */
export const SkipAuthorizationHeader = 'X-Skip-Authorization-Handler';

@Injectable()
export class AuthorizationInterceptor implements HttpInterceptor {

  private refreshTokenInProgress = false;
  private readonly refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);

  constructor(private readonly auth: AuthService) { }

  public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    // Abort if the request has instructed us via a custom header to do so
    if (req.headers.has(SkipAuthorizationHeader)) {
      // Delete the temporary header otherwise ASP.NET might get spooked by the unrecognised header
      const headers = req.headers.delete(SkipAuthorizationHeader);
      return next.handle(req.clone({ headers }));
    }

    if (!req.headers.has('Content-Type')) {
      req = req.clone({
        headers: req.headers.set('Content-Type', 'application/json')
      });
    }

    req = this.addAuthenticationToken(req);

    return next.handle(req).pipe(
      catchError((error: HttpErrorResponse) => {
        if (error && error.status === 401 && this.auth.canAttemptTokenRenewal) {
          // 401 errors are most likely going to be because we have an expired token that we need to refresh.
          if (this.refreshTokenInProgress) {
            // If refreshTokenInProgress is true, we will wait until refreshTokenSubject has a non-null value
            // which means the new token is ready and we can retry the request again
            return this.refreshTokenSubject.pipe(
              filter(result => result !== null),
              take(1),
              switchMap(() => next.handle(this.addAuthenticationToken(req)))
            );
          } else {
            this.refreshTokenInProgress = true;
            // Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
            this.refreshTokenSubject.next(null);
            return this.refreshAccessToken().pipe(
              switchMap((success: boolean) => {
                this.refreshTokenSubject.next(success);
                return next.handle(this.addAuthenticationToken(req));
              }),
              // When the call to refreshToken completes we reset the refreshTokenInProgress to false
              // for the next time the token needs to be refreshed
              finalize(() => this.refreshTokenInProgress = false)
            );
         }
        } else {
          throwError(error);
          return next.handle(req);
        }
      })
    );
  }

  private refreshAccessToken(): Observable<any> {
    return from(this.auth.renewTokensAsync());
  }

  private addAuthenticationToken(request: HttpRequest<any>): HttpRequest<any> {

    // If we do not have a token yet then we should not set the header.
    // Here we could first retrieve the token from where we store it.
    if (!this.auth.accessToken) {
      return request;
    }

    // If you are calling an outside domain then do not add the token.
    if (!request.url.match(environment.authDomainPattern)) {
      return request;
    }

    return request.clone({
      headers: request.headers.set('Authorization', `Bearer ${this.auth.accessToken}`)
    });
  }
}

这段代码似乎会导致所有失败的HTTP请求重试三次。我总是和rxjs做斗争,所以这显然是我在这里做的不好的事情,但我看不出是什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-23 11:04:07

这里

代码语言:javascript
运行
复制
 return next.handle(req).pipe(

阿德恩

代码语言:javascript
运行
复制
   } else {
      throwError(error);
      return next.handle(req);
    }

当您得到错误时,将调用else块!= 401。req是最初提出的请求。因此,在这里,您正在对错误执行完全相同的请求。

我不确定它是否应该是可触及的,因为我不记得throwError做了什么(从我使用角开始有一段时间了)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57162169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档