在Angular中,HTTP拦截器是一种特殊的服务,它允许你在HTTP请求发送到服务器之前或响应从服务器返回之后对其进行修改。拦截器通常用于添加认证头、处理错误、重定向等。
HTTP拦截器实现了HttpInterceptor
接口,该接口定义了一个intercept
方法。这个方法接收两个参数:一个是HttpRequest
对象,另一个是HttpHandler
对象。HttpHandler
是一个函数,它接收一个HttpRequest
并返回一个Observable<HttpEvent<any>>
。
下面是一个简单的HTTP拦截器示例,它在每个请求中添加一个认证令牌,并在响应返回之前打印日志。
import { Injectable } from '@angular/core';
import {
HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// 克隆请求并在头部添加认证令牌
const authReq = req.clone({
headers: req.headers.set('Authorization', 'Bearer your-auth-token')
});
// 打印请求信息
console.log('Request:', authReq);
// 发送请求并监听响应
return next.handle(authReq).pipe(
tap(event => {
if (event instanceof HttpResponse) {
// 打印响应信息
console.log('Response:', event);
}
}, error => {
// 处理错误
console.error('Error:', error);
})
);
}
}
如果你在测试HTTP拦截器时遇到了问题,比如在intercept
方法返回之前调用expect
失败,可能是因为你没有正确地订阅拦截器返回的Observable
。
问题原因:Observable
是异步的,如果你没有订阅它,那么expect
可能会在拦截器完成工作之前执行。
解决方法:确保你在测试中订阅了拦截器返回的Observable
。
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';
describe('AuthInterceptor', () => {
let httpMock: HttpTestingController;
let httpClient: HttpClient;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [AuthInterceptor]
});
httpMock = TestBed.inject(HttpTestingController);
httpClient = TestBed.inject(HttpClient);
});
afterEach(() => {
httpMock.verify();
});
it('should add authorization header', () => {
httpClient.get('/api/data').subscribe(response => {
expect(response).toBeTruthy();
});
const req = httpMock.expectOne('/api/data');
expect(req.request.headers.has('Authorization')).toBeTruthy();
req.flush({});
});
});
在这个测试示例中,我们使用HttpClientTestingModule
来模拟HTTP请求,并通过HttpTestingController
来验证请求是否按预期进行。我们订阅了httpClient.get
的调用结果,以确保在断言之前拦截器有机会修改请求。
领取专属 10元无门槛券
手把手带您无忧上云