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

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

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

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

描述你想要的解决方案

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

描述你考虑过的替代方案

  • 无响应*

附加上下文/截图

I found similar implementation using RxJs in angular where they pipeline the request when one response fail

import {throwError as observableThrowError,  Observable ,  BehaviorSubject } from 'rxjs';

import {take, filter, catchError, switchMap, finalize} from 'rxjs/operators';
import { Injectable, Injector } from "@angular/core";
import { HttpInterceptor, HttpRequest, HttpHandler, HttpSentEvent, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpErrorResponse } from "@angular/common/http";

import { AuthService } from "./auth.service";

@Injectable()
export class RequestInterceptorService implements HttpInterceptor {

    isRefreshingToken: boolean = false;
    tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);

    constructor(private injector: Injector) {}

    addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
        return req.clone({ setHeaders: { Authorization: 'Bearer ' + token }})
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
        const authService = this.injector.get(AuthService);

        return next.handle(this.addToken(req, authService.getAuthToken())).pipe(
            catchError(error => {
                if (error instanceof HttpErrorResponse) {
                    switch ((<HttpErrorResponse>error).status) {
case 400:
return this.handle400Error(error);
case 401:
return this.handle401Error(req, next);
default:
return observableThrowError(error);
}
} else {
return observableThrowError(error);
}
}));
    }

    handle400Error(error) {
        if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
            // If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
            return this.logoutUser();
        }

        return observableThrowError(error);
    }

    handle401Error(req: HttpRequest<any>, next: HttpHandler) {
        if (!this.isRefreshingToken) {
            this.isRefreshingToken = true;

            // Reset here so that the following requests wait until the token
            // comes back from the refreshToken call.
            this.tokenSubject.next(null);

            const authService = this.injector.get(AuthService);
            
            return authService.refreshToken().pipe(
                switchMap((newToken: string) => {
if (newToken) {
this.tokenSubject.next(newToken);
return next.handle(this.addToken(this.getNewRequest(req), newToken));
                    }

                    // If we don't get a new token, we are in trouble so logout.
return this.logoutUser();
}),
catchError(error => {
// If there is an exception calling 'refreshToken', bad news so logout.
return this.logoutUser();
}),
finalize(() => {
this.isRefreshingToken = false;
}),);
} else {
return this.tokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(token => {
return next.handle(this.addToken(this.getNewRequest(req), token));
}),);
}
}

/*
This method is only here so the example works.
Do not include in your code, just use 'req' instead of 'this.getNewRequest(req)'.
*/
getNewRequest(req: HttpRequest<any>): HttpRequest<any> {
if (req.url.indexOf('getData') > 0) {
return new HttpRequest('GET', 'http://private-4002d-testerrorresponses.apiary-mock.com/getData');
}

return new HttpRequest('GET', 'http://private-4002d-testerrorresponses.apiary-mock.com/getLookup');
}

logoutUser() {
// Route to the login page (implementation up to you)

return observableThrowError("");
}
}
mrwjdhj3

mrwjdhj31#

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

相关问题