Angular 6,不能应用多个HttpHeaders

Posted

技术标签:

【中文标题】Angular 6,不能应用多个HttpHeaders【英文标题】:Angular 6, multiple HttpHeaders can't be applied 【发布时间】:2019-01-15 21:46:46 【问题描述】:

目的: 使用 2 个默认标头发送请求:内容类型和授权(后端 - Web API)。 状况: Angular 6.0.1 版和使用生成器 ngx-rocket 构建的项目。 问题: 我为 Content-Type 添加了拦截器,它可以工作。

 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    request = request.clone(
      url: environment.serverUrl + request.url,
      setHeaders: 
        'Content-Type': 'application/x-www-form-urlencoded'
      ,
      body: this.convertToContentType(request.body)
    );
    return next.handle(request);
  

当我试图在同一个函数中添加另一个标题时,没有应用任何标题,并且在每种情况下都是相同的情况。它仅适用于一个标题。我试图添加另一个拦截器

@Injectable()
export class AuthorizationInterceptor implements HttpInterceptor 
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    const credentialsData = localStorage.getItem(token_key);
    if (credentialsData && JSON.parse(credentialsData)) 
      request = request.clone(
        // headers: new HttpHeaders().set('Authorization', `Bearer $JSON.parse(credentialsData).token`)
        setHeaders: 
          'Authorization': `Bearer $JSON.parse(credentialsData).token`
        
      );
    
    return next.handle(request);
  


这是我的 http.service.ts 服务代码

import Inject, Injectable, InjectionToken, Injector, Optional from '@angular/core';
import HttpClient, HttpEvent, HttpInterceptor, HttpHandler, HttpRequest from '@angular/common/http';
import Observable from 'rxjs';

import ErrorHandlerInterceptor from './error-handler.interceptor';
import CacheInterceptor from './cache.interceptor';
import ApiPrefixInterceptor from './api-prefix.interceptor';
import AuthorizationInterceptor from '@app/core/http/api-prefix.interceptor';

// HttpClient is declared in a re-exported module, so we have to extend the original module to make it work properly
// (see https://github.com/Microsoft/TypeScript/issues/13897)
declare module '@angular/common/http/src/client' 

  // Augment HttpClient with the added configuration methods from HttpService, to allow in-place replacement of
  // HttpClient with HttpService using dependency injection
  export interface HttpClient 

    /**
     * Enables caching for this request.
     * @param boolean forceUpdate Forces request to be made and updates cache entry.
     * @return HttpClient The new instance.
     */
    cache(forceUpdate?: boolean): HttpClient;

    /**
     * Skips default error handler for this request.
     * @return HttpClient The new instance.
     */
    skipErrorHandler(): HttpClient;

    /**
     * Do not use API prefix for this request.
     * @return HttpClient The new instance.
     */
    disableApiPrefix(): HttpClient;

    disableAuthorizationHeader(): HttpClient;

  



// From @angular/common/http/src/interceptor: allows to chain interceptors
class HttpInterceptorHandler implements HttpHandler 

  constructor(private next: HttpHandler, private interceptor: HttpInterceptor) 
  

  handle(request: HttpRequest<any>): Observable<HttpEvent<any>> 
    return this.interceptor.intercept(request, this.next);
  



/**
 * Allows to override default dynamic interceptors that can be disabled with the HttpService extension.
 * Except for very specific needs, you should better configure these interceptors directly in the constructor below
 * for better readability.
 *
 * For static interceptors that should always be enabled (like ApiPrefixInterceptor), use the standard
 * HTTP_INTERCEPTORS token.
 */
export const HTTP_DYNAMIC_INTERCEPTORS = new InjectionToken<HttpInterceptor>('HTTP_DYNAMIC_INTERCEPTORS');

/**
 * Extends HttpClient with per request configuration using dynamic interceptors.
 */
@Injectable()
export class HttpService extends HttpClient 

  constructor(private httpHandler: HttpHandler,
              private injector: Injector,
              @Optional() @Inject(HTTP_DYNAMIC_INTERCEPTORS) private interceptors: HttpInterceptor[] = []) 
    super(httpHandler);

    if (!this.interceptors) 
      // Configure default interceptors that can be disabled here
      this.interceptors = [
        this.injector.get(ApiPrefixInterceptor),
        // this.injector.get(AuthorizationInterceptor),
        this.injector.get(ErrorHandlerInterceptor)
      ];
    
  

  cache(forceUpdate?: boolean): HttpClient 
    const cacheInterceptor = this.injector.get(CacheInterceptor).configure(update: forceUpdate);
    return this.addInterceptor(cacheInterceptor);
  

  skipErrorHandler(): HttpClient 
    return this.removeInterceptor(ErrorHandlerInterceptor);
  

  disableApiPrefix(): HttpClient 
    return this.removeInterceptor(ApiPrefixInterceptor);
  

  disableAuthorizationHeader(): HttpClient 
    return this.removeInterceptor(AuthorizationInterceptor);
  

  // Override the original method to wire interceptors when triggering the request.
  request(method?: any, url?: any, options?: any): any 
    const handler = this.interceptors.reduceRight(
      (next, interceptor) => 
        return new HttpInterceptorHandler(next, interceptor);
      , this.httpHandler
    );
    return new HttpClient(handler).request(method, url, options);
  

  private removeInterceptor(interceptorType: Function): HttpService 
    return new HttpService(
      this.httpHandler,
      this.injector,
      this.interceptors.filter(i => !(i instanceof interceptorType))
    );
  

  private addInterceptor(interceptor: HttpInterceptor): HttpService 
    return new HttpService(
      this.httpHandler,
      this.injector,
      this.interceptors.concat([interceptor])
    );
  


我已经确定问题出在标头上,而不是拦截器机制上。

更新

这是请求网络选项卡的屏幕截图,以确保缺少标头。 Network screenshot

【问题讨论】:

您是否将授权标头暴露到您的后端? 看看这个***.com/questions/50968674/… @firegloves 我认为如果我发送标头,它们将在网络选项卡中可见。我看不到他们。我错了吗? 别想:试试 :) 我在开玩笑,我不记得你是否可以在网络选项卡中看到,也许不是 请记住,浏览器可以知道该特定标头是否有效,因为您已经与服务器进行了数据交换 【参考方案1】:

你试过这个代码吗

let headers = request.headers
        .set('Content-Type', 'application/json')
        .set('Authorization', `Bearer $JSON.parse(credentialsData).token`);

@Injectable()
export class AuthorizationInterceptor implements HttpInterceptor 
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    const credentialsData = localStorage.getItem(token_key);
    if (credentialsData && JSON.parse(credentialsData)) 
      request = request.clone( headers );
    
    return next.handle(request);
  


【讨论】:

很遗憾,是的【参考方案2】:

问题出在后端部分,可应用的标头有设置限制。

【讨论】:

以上是关于Angular 6,不能应用多个HttpHeaders的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6 组件

Angular 6 多个 @input() 级别

为 mat-select 预选多个值 - Angular 6

Angular 6 - 多个子组件应该是同一个实例

Angular 6 中 ngIf 中的多个条件

Angular2 使用一个 REST 调用的多个组件