angular - Angular 6 使用带有配置服务的 Http 拦截器
问题描述
我正在使用 Angular 6,问题是当我尝试使用拦截器作为应用程序模块提供程序以及 APP_INITIALIZER 从本地获取 json 配置文件时。
我的应用模块片段是:
../src/app/app.module.ts(提供者片段)
providers: [
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: initializeApp,
deps: [AppConfigService], multi: true
},
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true },
{ provide: LOCALE_ID, useValue: 'ES' },
Title,
]
有趣的是,如果我删除拦截器,代码可以很好地带来配置文件。我获取配置文件的代码是:
../src/app/_services/app-config.service.ts
import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment.dev';
import { IAppConfig } from '../_models/_interfaces/app-config.model';
@Injectable()
export class AppConfigService {
static settings: IAppConfig;
constructor(private http: HttpClient) {}
load() {
const jsonFile = `../../assets/config/config.${environment.name}.json`;
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile).toPromise().then((response: Response) => {
AppConfigService.settings = <IAppConfig>response;
resolve();
}).catch((response: any) => {
reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`);
});
});
}
}
最后,拦截器代码:
../src/app/_interceptors/token.interceptor.ts
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../_services/auth.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(public auth: AuthService) {}
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.auth.getToken()}`
}
});
return next.handle(request);
}
}
当 Angular 编译应用程序时,它返回:
无法加载文件“../../assets/config/config.dev.json”:{}
我尝试了几种方法试图避免这个问题,但直到现在都无法解决。
关于它的任何提示?
提前致谢。
解决方案
当您使用 HttpClient 获取配置文件时,您的拦截器也在过滤该请求。在您的代码中,拦截器正在用 Authorization 标头替换(不附加到现有的)所有 HTTP 标头。当默认的 Content-Type application/json 丢失时,请求不再起作用。使用 request.headers.append(...) 保存并修改旧标头,然后再将它们设置为克隆的标头。
或者
在拦截器中为您的文件请求定义一个例外。一种简单的方法是检查 request.url 中使用了哪个 URL
if (request.url.indexOf('config') > -1) {
requestModified = request.clone({
url: request.url,
headers: request.headers.set('Content-Type', 'application/json')
});
}
推荐阅读
- c# - 绑定 x:Load,更新绑定值不会加载控件 (UWP)
- c# - 如何将磁盘可用空间性能计数器添加到 Azure Application Insights?
- java - 用Java打印二维对象数组?
- javascript - Javascript:不支持属性或方法“hasAttribute”
- c# - 如何根据 C++ 在同一内存位置重新初始化 C# 中的对象(或者它是自动完成的)?
- haskell - 使用来自 hackage 的 SelfOrganizing map som 获取列表列表
- html - 将 div 拆分为多列而不破坏子元素
- wordpress - 如何在站点子域上运行 Wordpress 管理员?
- python - 使用 Xcode 10 编译 Cython
- angular - 带有 ng-template 的角 mat-tree