【问题标题】:Angular 6 use Http Interceptor with config serviceAngular 6 使用带有配置服务的 Http 拦截器
【发布时间】:2019-03-25 09:43:19
【问题描述】:

我正在使用 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”:{}

我尝试了几种方法来避免这个问题,但直到现在都无法解决。

有什么建议吗?

提前致谢。

【问题讨论】:

  • 请在拦截器前后显示请求。另外,jsonFile 看起来很奇怪,你为什么像遍历文件系统一样使用../..,它不应该以/assets 开头吗?

标签: angular config interceptor


【解决方案1】:

当您使用 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')
    });
}

【讨论】:

  • 嗨 micaro 我在我的代码中使用了你的建议来更改标头分配,但它仍然不起作用我将拦截器更改为一种方法,在该方法中我使用请求标头创建一个复制所有当前标头键的新对象和添加 Autorization Token 和 Content Type application/json,现在如果我删除了配置服务注入,那么拦截器添加 jwt 令牌一切正常。但是,如果我添加配置服务,它会返回相同的错误,而不是从资产加载文件......在这种情况下我不理解角度方式
  • 棘手的情况。尝试仅用 Content-Type 替换当前标题。不要在对本地文件的请求中使用授权令牌。我不确定这是否有什么不同。
  • 是的,真的很棘手,我替换了拦截器代码,全部更改为“console.log(request)”,如果我将两者(配置服务和拦截器)都作为提供者,它给了我相同的错误。如果我单独使用配置服务,它会为我带来配置文件值,如果我只使用拦截器(单独)并且它可以很好地向请求添加 jwt 令牌,但如果我同时尝试两者,则会失败。如果我上传任何其他代码以更好地检查它,也许会更好?
  • 我在这里找到了一个可行的解决方案:stackoverflow.com/questions/46469349/…,我使用了第二个建议,稍后我会检查第一个,我在这个问题上浪费了很多时间。感谢米卡罗的帮助。我仍然不明白问题出在哪里,因为听起来不错。
  • 不错。 HttpBackend 注入对我来说是新事物。我习惯于在拦截器中为不同类型的请求定义不同的函数。我以前从未遇到过上传或下载文件的问题。生活和学习:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 2019-06-04
  • 2018-12-24
  • 2018-07-08
  • 2022-01-04
  • 2023-03-13
相关资源
最近更新 更多