我有一个带有HttpInterceptor的核心模块用于授权处理,我在AppModule中包含了这个模块,这样使用HttpClient的所有其他模块都在使用这个拦截器。
@NgModule({
imports: [],
declarations: [],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
},
]
})
export class CoreModule { }
如何使模块绕过默认拦截器?
@NgModule({
imports: [
CommonModule
],
declarations: components,
providers: [CustomService],
exports: components,
})
export class ModuleWithoutInterceptorModule { }
答案 0 :(得分:70)
你可以使用HttpBackend。
示例:
import { HttpClient, ..., HttpBackend } from '@angular/common/http';
@Injectable()
export class TestService {
private httpClient: HttpClient;
constructor( handler: HttpBackend) {
this.httpClient = new HttpClient(handler);
}
....
通过这种方式,服务不会被AuthInterceptor截获。
答案 1 :(得分:29)
GitHub上的每this suggestion,我们已经实现了一个简单的标头来识别不应被拦截的请求。在拦截器中:
export const InterceptorSkipHeader = 'X-Skip-Interceptor';
@Injectable()
export class SkippableInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.headers.has(InterceptorSkipHeader)) {
const headers = req.headers.delete(InterceptorSkipHeader);
return next.handle(req.clone({ headers }));
}
... // intercept
}
}
然后,只要您想跳过特定请求的拦截:
const headers = new HttpHeaders().set(InterceptorSkipHeader, '');
this.httpClient
.get<ResponseType>(someUrl, { headers })
...
请注意,使用此方法时, service 而不是拦截器会在拦截器的逻辑应用时选择;这意味着服务必须“知道”应用程序中的拦截器。根据您的使用情况,最好让拦截器决定何时应用逻辑。
答案 2 :(得分:2)
为了绕过所有拦截器,我们可以使用HttpBackend作为@deg建议。
在其他情况下,我们可以创建HttpClient工厂,该工厂将允许我们从拦截器链中排除拦截器:
import { createHttpClient } from './http-client.factory';
...
@Injectable({
providedIn: 'root'
})
export class TodosApiService {
http = createHttpClient(this.injector, [Interceptor2]);
^^^^^^^^^^^^
Interceptors to exclude
constructor(private injector: Injector) { }
getTodo() {
// Interceptor2 will be bypassed
return this.http.get('https://jsonplaceholder.typicode.com/todos')
}
}
请注意,您可以通过创建基类来重用此逻辑:
@Injectable()
export class BasicHttpClient {
protected http = createHttpClient(this.injector, [Interceptor2]);
constructor(private injector: Injector) { }
}
@Injectable({ providedIn: 'root' })
export class TodosApiService extends BaseHttpClient {
getTodo() {
// Interceptor2 will be bypassed
return this.http.get('https://jsonplaceholder.typicode.com/todos')
}
}
http-client.factory.ts
import {
HTTP_INTERCEPTORS,
HttpBackend,
HttpClient,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { Injector, Type } from '@angular/core';
class HttpInterceptorHandler implements HttpHandler {
constructor(private next: HttpHandler, private interceptor: HttpInterceptor) {}
handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
return this.interceptor.intercept(req, this.next);
}
}
class HttpInterceptingHandler implements HttpHandler {
private chain: HttpHandler | null = null;
constructor(
private backend: HttpBackend,
private injector: Injector,
private interceptorsToExclude: Type<HttpInterceptor>[],
private intercept?: (req: HttpRequest<any>) => HttpRequest<any>
) {}
handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
if (this.intercept) {
req = this.intercept(req);
}
if (this.chain === null) {
const interceptors = this.injector
.get(HTTP_INTERCEPTORS, [])
.filter(
interceptor => !this.interceptorsToExclude.some(interceptorType => interceptor instanceof interceptorType)
);
this.chain = interceptors.reduceRight(
(next, interceptor) => new HttpInterceptorHandler(next, interceptor),
this.backend
);
}
return this.chain.handle(req);
}
}
export function createHttpClient(
injector: Injector,
excludedInterceptors: Type<HttpInterceptor>[],
intercept?: (req: HttpRequest<any>) => HttpRequest<any>
) {
return new HttpClient(
new HttpInterceptingHandler(injector.get(HttpBackend), injector, excludedInterceptors, intercept)
);
}