Ale*_*aru 43 angular-http-interceptors angular
我有一个带有HttpInterceptor的核心模块用于授权处理,我在AppModule中包含了这个模块,这样使用HttpClient的所有其他模块都使用这个拦截器.
@NgModule({
imports: [],
declarations: [],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
},
]
})
export class CoreModule { }
Run Code Online (Sandbox Code Playgroud)
如何使模块绕过默认拦截器?
@NgModule({
imports: [
CommonModule
],
declarations: components,
providers: [CustomService],
exports: components,
})
export class ModuleWithoutInterceptorModule { }
Run Code Online (Sandbox Code Playgroud)
小智 107
你可以使用HttpBackend.
例:
import { HttpClient, ..., HttpBackend } from '@angular/common/http';
@Injectable()
export class TestService {
private httpClient: HttpClient;
constructor( handler: HttpBackend) {
this.httpClient = new HttpClient(handler);
}
....
Run Code Online (Sandbox Code Playgroud)
通过这种方式,服务不会被AuthInterceptor拦截.
jon*_*rpe 50
根据GitHub上的这个建议,我们实现了一个简单的标头来识别不应被拦截的请求.在拦截器中:
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
}
}
Run Code Online (Sandbox Code Playgroud)
然后,只要您想跳过特定请求的拦截:
const headers = new HttpHeaders().set(InterceptorSkipHeader, '');
this.httpClient
.get<ResponseType>(someUrl, { headers })
...
Run Code Online (Sandbox Code Playgroud)
请注意,使用此方法时,服务(而非拦截器)在拦截器的逻辑应用时选择; 这意味着服务必须"知道"应用程序中的拦截器.根据您的使用情况,最好让拦截器决定何时应用逻辑.
为了绕过所有拦截器,我们可以按照@deg 的建议使用 HttpBackend。
在其他情况下,我们可以创建 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')
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您可以通过创建基类来重用此逻辑:
@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')
}
}
Run Code Online (Sandbox Code Playgroud)
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)
);
}
Run Code Online (Sandbox Code Playgroud)
从Angular 12HttpContext开始,这可以通过属性来完成HttpRequest!
这种方法很好,因为它不需要任何剥离标头的逻辑,并且可以在每个请求的基础上完成。
export const DISABLE_GLOBAL_EXCEPTION_HANDLING = new HttpContextToken<boolean>(() => false);
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.ignoreErrorHandling(request)) {
return next.handle(request);
}
return next.handle(request).pipe(
catchError((error) => {
// normal intercepting logic
return throwError(() => error);
}),
);
private ignoreErrorHandling(request: HttpRequest<any>) {
return request.context.get(DISABLE_GLOBAL_EXCEPTION_HANDLING);
}
Run Code Online (Sandbox Code Playgroud)
可以通过添加令牌来禁用单个请求:
this.httpClient.get<ResponseType>(`/api`, {
context: new HttpContext().set(DISABLE_GLOBAL_EXCEPTION_HANDLING, true),
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20928 次 |
| 最近记录: |