axios 管道请求,直到在拦截器中设置访问令牌为止,

js81xvg6  于 9个月前  发布在  iOS
关注(0)|答案(1)|浏览(164)

你的功能请求是否与问题相关?请描述。

当同时进行多个API调用时,当前的拦截器会将所有响应保存在队列中,然后再调用原始请求。
相反,我希望实现类似于流水线请求的功能,即如果一个API调用抛出401或403错误,那么就保持其他请求在请求拦截器中暂停,而不是像当前的做法一样将失败的请求放入队列。
类似这样的功能已经在Angular中使用RxJS实现了。

描述你想要的解决方案

设置一些标志来表示第一个请求已经返回了401或403响应,因此不要调用所有其他API,然后等待其他返回403状态的API,而是采用当前的做法:回调失败的API队列。
如果一个API失败并且正在刷新,则将其他请求保留在请求管道中。
如果设置了刷新令牌,则仅处理该请求。

描述你考虑过的替代方案

  • 无响应*

附加上下文/截图

  1. I found similar implementation using RxJs in angular where they pipeline the request when one response fail
  2. import {throwError as observableThrowError, Observable , BehaviorSubject } from 'rxjs';
  3. import {take, filter, catchError, switchMap, finalize} from 'rxjs/operators';
  4. import { Injectable, Injector } from "@angular/core";
  5. import { HttpInterceptor, HttpRequest, HttpHandler, HttpSentEvent, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpErrorResponse } from "@angular/common/http";
  6. import { AuthService } from "./auth.service";
  7. @Injectable()
  8. export class RequestInterceptorService implements HttpInterceptor {
  9. isRefreshingToken: boolean = false;
  10. tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
  11. constructor(private injector: Injector) {}
  12. addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
  13. return req.clone({ setHeaders: { Authorization: 'Bearer ' + token }})
  14. }
  15. intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
  16. const authService = this.injector.get(AuthService);
  17. return next.handle(this.addToken(req, authService.getAuthToken())).pipe(
  18. catchError(error => {
  19. if (error instanceof HttpErrorResponse) {
  20. switch ((<HttpErrorResponse>error).status) {
  21. case 400:
  22. return this.handle400Error(error);
  23. case 401:
  24. return this.handle401Error(req, next);
  25. default:
  26. return observableThrowError(error);
  27. }
  28. } else {
  29. return observableThrowError(error);
  30. }
  31. }));
  32. }
  33. handle400Error(error) {
  34. if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
  35. // If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
  36. return this.logoutUser();
  37. }
  38. return observableThrowError(error);
  39. }
  40. handle401Error(req: HttpRequest<any>, next: HttpHandler) {
  41. if (!this.isRefreshingToken) {
  42. this.isRefreshingToken = true;
  43. // Reset here so that the following requests wait until the token
  44. // comes back from the refreshToken call.
  45. this.tokenSubject.next(null);
  46. const authService = this.injector.get(AuthService);
  47. return authService.refreshToken().pipe(
  48. switchMap((newToken: string) => {
  49. if (newToken) {
  50. this.tokenSubject.next(newToken);
  51. return next.handle(this.addToken(this.getNewRequest(req), newToken));
  52. }
  53. // If we don't get a new token, we are in trouble so logout.
  54. return this.logoutUser();
  55. }),
  56. catchError(error => {
  57. // If there is an exception calling 'refreshToken', bad news so logout.
  58. return this.logoutUser();
  59. }),
  60. finalize(() => {
  61. this.isRefreshingToken = false;
  62. }),);
  63. } else {
  64. return this.tokenSubject.pipe(
  65. filter(token => token != null),
  66. take(1),
  67. switchMap(token => {
  68. return next.handle(this.addToken(this.getNewRequest(req), token));
  69. }),);
  70. }
  71. }
  72. /*
  73. This method is only here so the example works.
  74. Do not include in your code, just use 'req' instead of 'this.getNewRequest(req)'.
  75. */
  76. getNewRequest(req: HttpRequest<any>): HttpRequest<any> {
  77. if (req.url.indexOf('getData') > 0) {
  78. return new HttpRequest('GET', 'http://private-4002d-testerrorresponses.apiary-mock.com/getData');
  79. }
  80. return new HttpRequest('GET', 'http://private-4002d-testerrorresponses.apiary-mock.com/getLookup');
  81. }
  82. logoutUser() {
  83. // Route to the login page (implementation up to you)
  84. return observableThrowError("");
  85. }
  86. }
mrwjdhj3

mrwjdhj31#

Yrajaram112,你能给我分配这个问题吗?我想在这个项目上工作。

相关问题