Angular HttpInterceptor RangeError: Maximum call stack size exceeded
Angular HttpInterceptor RangeError: Maximum call stack size exceeded
我的 HttpInterceptor 在短时间内调用多次导致出现错误:RangeError:超出最大调用堆栈大小。
我的 HttpInterceptor 正在拦截每个向 header 添加不记名令牌的请求。第一次通过拦截器时,它将从身份验证服务器获取令牌,这会导致在短时间内对身份验证器进行多次 POST 调用。我想这是因为当它在 header 中没有持有者令牌时,拦截器将使用 HttpClient 进行调用,导致拦截器再次 传递 true 并继续调用 GetAuthToken() 结果循环直到出现错误。
我试图忽略 header 中带有标志的请求,但它仍然在循环。您对如何解决这个问题有什么建议吗?
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('INTERCEPTOR');
// We retrieve the token, if any
const token = this.GetAuthToken();
let newHeaders = req.headers;
if (token) {
// If we have a token, we append it to our new headers
newHeaders = newHeaders.append('Authorization', "bearer " + token);
}
// Finally we have to clone our request with our new headers
// This is required because HttpRequests are immutable
const authReq = req.clone({headers: newHeaders});
// Then we return an Observable that will run the request
// or pass it to the next interceptor if any
return next.handle(authReq);
}
GetAuthToken(): any{
if (localStorage.getItem('access_token') != null){
return localStorage.getItem('access_token');
}
let httpHeaders = new HttpHeaders({
'Content-Type' : 'application/x-www-form-urlencoded'
});
let options = {
headers: httpHeaders
};
let body = `grant_type=${this.grant_type}&client_id=${this.client_id}&username=${this.username}&password=${this.password}`
this._http.post<AuthResponse>(this.url, body, options).subscribe(result => {
localStorage.setItem('access_token', result.access_token);
localStorage.setItem('refresh_token', result.refresh_token);
return result.access_token;
});
}
你的拦截器拦截所有,甚至你在 GetAuthToken 中的调用,你需要使用“if”来跳过来自 GetAuthToken 的调用
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.body==`grant_type=${this.grant_type}&client_id=${this.client_id}&username=${this.username}&password=${this.password}`)
return next.handle(req);
...rest of your code..
}
您还可以添加一个“傻瓜header”,就像this SO
中显示的那样
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.headers.get("skip")){
const newHeader=req.headers.delete("skip");
const newreq= req.clone({headers: newHeaders});
return next.handle(newreq);
}
...rest of your code..
}
并在 GetAuthToken()
GetAuthToken(){
...
let options = {
headers: httpHeaders.Add("skip",true)
};
...
}
我的 HttpInterceptor 在短时间内调用多次导致出现错误:RangeError:超出最大调用堆栈大小。
我的 HttpInterceptor 正在拦截每个向 header 添加不记名令牌的请求。第一次通过拦截器时,它将从身份验证服务器获取令牌,这会导致在短时间内对身份验证器进行多次 POST 调用。我想这是因为当它在 header 中没有持有者令牌时,拦截器将使用 HttpClient 进行调用,导致拦截器再次 传递 true 并继续调用 GetAuthToken() 结果循环直到出现错误。
我试图忽略 header 中带有标志的请求,但它仍然在循环。您对如何解决这个问题有什么建议吗?
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('INTERCEPTOR');
// We retrieve the token, if any
const token = this.GetAuthToken();
let newHeaders = req.headers;
if (token) {
// If we have a token, we append it to our new headers
newHeaders = newHeaders.append('Authorization', "bearer " + token);
}
// Finally we have to clone our request with our new headers
// This is required because HttpRequests are immutable
const authReq = req.clone({headers: newHeaders});
// Then we return an Observable that will run the request
// or pass it to the next interceptor if any
return next.handle(authReq);
}
GetAuthToken(): any{
if (localStorage.getItem('access_token') != null){
return localStorage.getItem('access_token');
}
let httpHeaders = new HttpHeaders({
'Content-Type' : 'application/x-www-form-urlencoded'
});
let options = {
headers: httpHeaders
};
let body = `grant_type=${this.grant_type}&client_id=${this.client_id}&username=${this.username}&password=${this.password}`
this._http.post<AuthResponse>(this.url, body, options).subscribe(result => {
localStorage.setItem('access_token', result.access_token);
localStorage.setItem('refresh_token', result.refresh_token);
return result.access_token;
});
}
你的拦截器拦截所有,甚至你在 GetAuthToken 中的调用,你需要使用“if”来跳过来自 GetAuthToken 的调用
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.body==`grant_type=${this.grant_type}&client_id=${this.client_id}&username=${this.username}&password=${this.password}`)
return next.handle(req);
...rest of your code..
}
您还可以添加一个“傻瓜header”,就像this SO
中显示的那样intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.headers.get("skip")){
const newHeader=req.headers.delete("skip");
const newreq= req.clone({headers: newHeaders});
return next.handle(newreq);
}
...rest of your code..
}
并在 GetAuthToken()
GetAuthToken(){
...
let options = {
headers: httpHeaders.Add("skip",true)
};
...
}