我使用的是Angular 4.3.1和HttpClient。有一个HttpInterceptor来设置一些标题。
在某些http get请求中,我需要设置不同的标头。无论如何我可以为这个特定的HttpRequest传递一些param给这个HttpInterceptor吗?
@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(request.custom.param1) // how can i do this
request = request.clone({
setHeaders: {
'header1': 'xxxxxx'
}
});
else
request = request.clone({
setHeaders: {
'header2': 'yyyyyy'
}
});
return next.handle(request);
}
}
答案 0 :(得分:11)
我写了一个用于处理Http错误响应的拦截器。我想允许特定的Http调用来指示拦截器忽略某些响应状态代码,同时还保留将params传递给Http调用的能力。这是我最终得到的解决方案。 (谢谢,Aleksey在你的回答中提出了最初的想法)。
扩展HttpParams:
import { HttpParams } from '@angular/common/http';
import { HttpParamsOptions } from '@angular/common/http/src/params';
// Cause the HttpErrorInterceptor to ignore certain error response status codes like this:
//
// this.http.get<TypeHere>(`URL_HERE`, {
// params: new InterceptorHttpParams({ statusCodesToIgnore: [400, 401] }, {
// complete: 'false',
// offset: '0',
// limit: '50'
// })
// })
export class InterceptorHttpParams extends HttpParams {
constructor(
public interceptorConfig: { statusCodesToIgnore: number[] },
params?: { [param: string]: string | string[] }
) {
super({ fromObject: params } as HttpParamsOptions);
}
}
拦截器:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
tap(
() => {},
(error: any) => {
if (error instanceof HttpErrorResponse) {
const regEx = /^[4-5][0-9][0-9]$/; // 4XX and 5XX status codes
if (regEx.test(error.status.toString())) {
const errorMessage = this.getErrorMessageFromStatus(error.status);
if (!this._shouldIgnoreError(req, error)) {
console.log(`ERROR INTERCEPTOR: ${error.status}`);
this.toastService.alert(errorMessage);
}
}
}
})
);
}
// Based on `request.params.interceptorConfig.statusCodesToIgnore`, we can see if we should ignore this error.
_shouldIgnoreError(request: HttpRequest<any>, errorResponse: HttpErrorResponse) {
if (request.params instanceof InterceptorHttpParams
&& Array.isArray(request.params.interceptorConfig.statusCodesToIgnore)
&& request.params.interceptorConfig.statusCodesToIgnore.includes(errorResponse.status)) {
return true;
}
return false;
}
答案 1 :(得分:10)
也许有更好的方法来处理这个问题,但作为一种解决方法,您可以创建并传递自定义HttpParams
来请求,然后在拦截器中检查它们。例如:
export class CustomHttpParams extends HttpParams {
constructor(public param1: boolean) {
super();
}
}
在http调用中使用此类:
this.http.get('https://example.com', {
params: new CustomHttpParams(true)
})
现在在拦截器中:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.params instanceof CustomHttpParams && request.params.param1)
request = request.clone({
setHeaders: {
'header1': 'xxxxxx'
}
});
else
request = request.clone({
setHeaders: {
'header2': 'yyyyyy'
}
});
return next.handle(request);
}
答案 2 :(得分:1)
当前,Angular不支持通过HttpRequest对象传递“拦截器配置/元数据”(在相当长一段时间内它一直是open issue)。
作为一种可能的解决方法,我们可以定义一个新的MyHttpParams
类,该类扩展了Angular的HttpParams
,并添加了一个新的interceptorMetadata
属性。
请注意,MyHttpParams
必须覆盖append
,set
和delete
方法,以便它们返回MyHttpParams
而不是Angular的HttpParams
。如果我们不这样做,则调用这些方法时,interceptorMetadata
将被“丢弃”(例如,如果拦截器添加了一些HTTP参数,则下一个拦截器将不会获得interceptorMetadata
)。>
import {HttpParams} from '@angular/common/http';
export interface InterceptorMetadata {
readonly customParam1: string;
readonly customParam2: number;
// etc.
}
export interface MyHttpParamsConfig {
interceptorMetadata: Partial<InterceptorMetadata>;
params: string | Record<string, string | string[]>; // the actual params which will be included in the real request
}
export class MyHttpParams extends HttpParams {
public readonly interceptorMetadata: Partial<InterceptorMetadata>;
constructor({params, interceptorMetadata}: Partial<MyHttpParamsConfig> = {}) {
if(typeof params === 'string') {
super({fromString: params});
}
else if(typeof params === 'object') {
super({fromObject: params});
}
else {
super();
}
this.interceptorMetadata = interceptorMetadata;
}
// orverrides HttpParams.append
append(param: string, value: string): MyHttpParams {
const updatedHttpParams = super.append(param, value);
return new MyHttpParams({
interceptorMetadata: this.interceptorMetadata,
params: updatedHttpParams.toString()
});
}
// orverrides HttpParams.set
set(param: string, value: string): MyHttpParams {
const updatedHttpParams = super.set(param, value);
return new MyHttpParams({
interceptorMetadata: this.interceptorMetadata,
params: updatedHttpParams.toString()
});
}
// orverrides HttpParams.delete
delete(param: string, value?: string): MyHttpParams {
const updatedHttpParams = super.delete(param, value);
return new MyHttpParams({
interceptorMetadata: this.interceptorMetadata,
params: updatedHttpParams.toString()
});
}
}
然后例如,当调用HttpClient.get()时,我们可以传递扩展的MyHttpParams的实例:
const myHttpParams = new MyHttpParams({
interceptorMetadata: {
customParam1: 'test', // this will NOT be part of the final request
},
params: 'someActualUrlQueryString=someValue' // this will be part of the final request
});
httpClient.get(myUrl, {params: myHttpParams})
最后,在拦截器中,我们可以使用interceptorMetadata
:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const {params} = req;
if(params instanceof MyHttpParams) {
if (params.interceptorMetadata && params.interceptorMetadata.customParam1 === 'test') {
// do something
}
}
// ...
}
感谢JWess为其提供的原始答案(它只是缺少append
,set
和delete
覆盖)
答案 3 :(得分:0)
您可以使用request的setParam选项。
export class WebReqInterceptor implements HttpInterceptor {
stringifiedData: any;
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (window.sessionStorage.getItem('token')) {
this.stringifiedData=JSON.parse(window.sessionStorage.getItem('token'));
request = request.clone({
setParams:{
access_token:this.stringifiedData.access_token
}
});
return next.handle(request);
}
else{
return next.handle(request);
}
}
}
答案 4 :(得分:0)
对于偶然发现相同问题的任何人,我们可以在 Angular 的新版本中在 HttpParams 中传递自定义参数。但是我们必须记住 HttpParams 是一个不可变对象。对于不可变对象,每次调用 params.append() 都会返回一个新对象。因此,我们必须将返回的新对象重新分配回 params,如下所示,
var params = new HttpParams();
// Notice that I am re-assigning the params object
params = params.append('showErrorMessage', 'false');
return this.http.get(url, { params: params });
在拦截器中,我们可以这样访问值
req.params.get('showErrorMessage')