我已经建立了一个使用API的AngularJS网站.此API提供的功能很少,如身份验证(Oauth).
当API返回401错误时,表示access_token已过期,需要使用refresh_token.
我在AngularJS中创建了一个拦截器.其目标是检查API返回的结果是否为401错误,如果是这种情况,则必须刷新令牌,然后处理先前被拒绝的请求.
问题是拦截器创建了一个无限循环.在初始请求的第二次失败之后,它应该停止但它不会.
angular.module('myApp')
.factory('authInterceptor', function ($rootScope, $q, $window, $injector) {
return {
// If the API returns an error
'responseError' : function(rejection) {
// If it's a 401
if (rejection.status == 401) {
var deferred = $q.defer();
$injector.get('$http').post('http://my-api.local/api/oauth/token', {
grant_type : 'refresh_token',
client_id : 'id',
client_secret : 'secret',
refresh_token : $window.sessionStorage.refresh_token
}, {
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
transformRequest : function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + …Run Code Online (Sandbox Code Playgroud) 我有一个问题,使我的缓存更简单.我认为有更好的方法来做到这一点.我的问题是我必须在每个get()函数中执行此"缓存"代码,这会导致代码更长.有谁帮助如何做到这一点最好的方式?谢谢.这是我的代码如下.我在我的代码中做的是我在news.service.ts中执行get()函数以从http获取数据,并在我的新闻列表中订阅它.
news.service.ts
getAllNews() {
if(this.newslist != null) {
return Observable.of(this.newslist);
}
else {
return this.httpClient
.get('http://sample.com/news')
.map((response => response))
.do(newslist => this.newslist = newslist)
.catch(e => {
if (e.status === 401) {
return Observable.throw('Unauthorized');
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
新闻list.service.ts
this.subscription = this.newsService.getAllNews()
.subscribe(
(data:any) => {
console.log(data);
this.newslists = data.data.data;
},
error => {
this.authService.logout()
this.router.navigate(['signin']);
});
}
Run Code Online (Sandbox Code Playgroud) 我已经实现了令牌保存,检索和我也有刷新调用的逻辑.问题是,当我在我的HttpInterceptor中拦截403时,同时进行的其他调用也会刷新令牌.在我的令牌刷新之前,我很想接听这些电话.创建我称之为"信号量"的请求.
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private auth: AuthService;
constructor(private injector: Injector) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.auth = this.injector.get(AuthService);
if(this.auth.isAuthenticated()){
request = request.clone({
setHeaders: {
Accept: 'application/json',
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
} else {
request = request.clone({
setHeaders: {
Accept: 'application/json'
}
});
}
return next.handle(request).catch(error => {
if (error.status === 401) {
console.log('refreshing token');
// TODO: return Refresh Token here and hold other calls
}
return Observable.throw(error);
});
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试显示ng4-loading-spinner对我的API进行HTTP调用的微调器.
我的代码基于以下链接中的示例:
我的Angular 5应用程序有多个多个模块.HTTP拦截器位于"服务"模块中.
我认为我有一个依赖注入问题,因为当我使用Chrome Dev Tools调试代码时,代码HTTP拦截器代码无法执行.
API-interceptor.ts
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch'
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpResponse
} from '@angular/common/http';
import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
@Injectable()
export class ApiInterceptor implements HttpInterceptor {
private count: number = 0;
constructor(private spinner: Ng4LoadingSpinnerService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.count++;
if (this.count == 1) this.spinner.show();
let handleObs: Observable<HttpEvent<any>> = next.handle(req);
handleObs
.catch((err: …Run Code Online (Sandbox Code Playgroud) 因此,我使用如下基本拦截器创建了一个angular2模块来处理HTTP拦截:
@Injectable()
export class RequestInterceptor implements HttpInterceptor {
constructor(private injector: Injector) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.injector.get(AuthService);
if(authService.isAuthenticated()){
const authReq = request.clone({
setHeaders: {
Authorization: `Bearer ${authService.getAccessToken()}`
}
});
let handle = next.handle(authReq).do(event => {
if(event instanceof HttpResponse){
if(event.headers.has('Authorization')){
authService.updateToken(event.headers.get('Authorization').split(' ')[1]);
}
}
});
return handle;
}else{
return next.handle(request);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当从服务器发送一个新的授权标头时,它将为http请求添加一个授权标头,并更新其自己的标头。它的导入和正常提供如下:
{
provide: HTTP_INTERCEPTORS,
useClass: RequestInterceptor,
multi: true
},
Run Code Online (Sandbox Code Playgroud)
因此,将auth angular2模块编译并导入到我的app.module.t中,效果很好。直到我尝试从子模块中使用它。此处的最高答案:Angular2中从父模块到子模块的继承导入声称angular2不会让您全局使用整个应用程序。它是否正确?
通过导入RequestInterceptor并在模块的提供程序中对其进行设置,我可以从子模块中获得该功能,但是我不想这样做,以使其使用起来不那么麻烦。
我希望获取第一个 http 请求的标头http://localhost:4200/
为了启动我的应用程序,我转到 URL http://localhost:4200/,我想在控制台中写入 http 入口的标头。
有谁知道这是否可能?
我尝试使用拦截器,但我只拦截应用程序的 http 请求和响应排序。
我的角度应用程序中有以下 http 拦截器,我想使用 Jasmine 对其进行单元测试。我用谷歌搜索了其中一些并尝试过,但它没有按预期工作。请找到下面的HttpInterceptorService.ts文件代码
export class HttpInterceptorService Implements HttpInterceptor {
counter = 0;
constructor(private loaderService: LoaderService) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
if (req.url !== '/getUsers') {
this.counter ++;
}
this.loaderService.setStatus(true);
return next.handle(req).pipe(
finalize(() => {
if (req.url !== 'getUsers') {
this.counter --;
}
if (this.counter === 0) {
this.loaderService.setStatus(false);
}
};
);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我目前尝试过的 HttpInterceptor.service.spec.ts 文件代码。我不确定如何测试其中的特定方法。
describe('HttpInterceptorService', () => {
let httpService: HttpService;
let httpMock: HttpTestingController;
let interceptor: HttpInterceptorService;
beforeEach(()=> {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [ …Run Code Online (Sandbox Code Playgroud) 在我们的Angular 4.3项目中,我们分别有公共站点组件和安全站点(登录)组件。我们使用@angular/common/http. 我们想为public-site组件和secured-site组件实现不同的http拦截器。例如,
LoggingInterceptorLoggingInterceptorAuthTokenInterceptor(在请求标头中传递身份验证令牌)我们尝试使用不同的拦截器HTTP_INTERCEPTORS在每个组件级别添加提供者详细信息@Component。但是请求不会进入任何拦截器。
仅当我们HTTP_INTERCEPTORS在@NgModule. 这里的问题是,公共站点 http 请求也会进入AuthTokenInterceptor不需要的。
那么我们应该如何解决这个问题呢?谢谢。
我在 Angular 5 中有一个有效的拦截器。它在 App.module 的提供者中注册,并正确拦截了从应用程序发出的所有请求。
问题是它不会拦截从应用程序使用的库发出的请求。
我正在使用开源库 (NGX-Jsonapi),并且需要拦截器在库向后端发出的每个请求中提供令牌。
有人遇到同样的问题吗?
编辑:该库使用 HttpClient。
我有以下角度的 http 拦截器
import { Injectable, Inject } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { tap } from "rxjs/operators";
import { ToastrService } from 'ngx-toastr';
import { NgxSpinnerService } from "ngx-spinner";
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
constructor(
@Inject('API_URL') private baseUrl: string,
public router: Router,
public toasterService: ToastrService,
private spinner: NgxSpinnerService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { …Run Code Online (Sandbox Code Playgroud) angular ×9
angular5 ×2
angular-http ×1
angularjs ×1
caching ×1
header ×1
http ×1
http-headers ×1
interceptor ×1
jasmine ×1
rxjs ×1
unit-testing ×1