繁体   English   中英

如何告诉Angular 2停止自动设置Content-Type标头?

[英]How can I tell Angular 2 to stop setting Content-Type headers automatically?

我目前正在尝试使用Angular 2(通过Ionic 2)应用程序访问API。 我们的laravel后端的设置方式使得它需要一个包含请求内容类型的Accept标头,而不是Content-Type标头。 不只是一个空的Content-Type标头,而且根本没有。

所以,我在Http中设置了必要的参数,在Headers中省略了Content-Type,这就是问题的开始:Angular 2显然无法保持其内容类型。 如果我给它一个对象作为请求的主体,它将Content-Type设置为application / json。 这仍然是可以理解的。 然后我对Object进行字符串化,这会导致Angular将Content-Type设置为text / plain。 尝试,通过

headers = new Header({Accept: 'application/json', Content-Type: undefined});

要么

headers.append("Content-Type", undefined);

或者我想象的任何标题的任何其他组合包含一个接受应用程序/ json而没有别的,甚至headers.set或headers.delete失败,Angular 2继续做它的事情。

在其他地方建议将Content-Type设置为undefined,我也尝试将其设置为空字符串,在传递字符串化的JSON时将其设置为application / json,Angular只是不会给出我想要的内容。 有没有办法扭转这种自动化? 我还在做错什么(我正在导入Headers,其中也就是缺少它,在其他地方是一个问题,所以应该出来)?

代码如下:

import { Injectable, Inject } from '@angular/core';

import { Http, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/toPromise';

import { ConfsService } from '../confs/confs.service';

import { ApiRequestBody }   from './api.request.body';

@Injectable()
export class ApiService {
    constructor(public confs: ConfsService, private apiRequestBody: ApiRequestBody, private http: Http) {

    post (method: string, data: any):Promise<any> {
        const api = this.confs.get().api;
        const url = api['server'] + "" + api[method];
        let allParams = this.apiRequestBody.toJSON(data);
        let body = JSON.stringify(allParams);
        let headers = new Headers({
            'Accept': 'application/json',
            'Content-Type': undefined,
        });
        let options = new RequestOptions({ headers: headers });     
        let obj = this.http.post(url, body, options).toPromise();
        return obj;
    }
}

ConfsService只获取一些配置参数,即api服务器URL,ApiRequestBody获取一个服务,该服务创建API甚至需要查看请求的一组标准参数,以及通过数据传递的参数。参数(然后合并到toJSON方法中的标准参数) - 没有火箭科学。 我正在做一个toPromise()因为我发现在这种特殊情况下的承诺更容易处理。

在深入研究Angular源代码后,我得出结论认为这是不可能的。 请参阅static_request.ts( https://github.com/angular/angular/blob/5293794316cc1b0f57d5d88b3fefdf6ae29d0d97/packages/http/src/static_request.ts ),它将首先检查您是否已手动将标头设置为特定字符串,并且未定义或者空字符串将落入detectContentTypeFromBody函数,该函数仅在您的请求正文为空时才设置ContentType.NONE。

  /**
   * Returns the content type enum based on header options.
   */
  detectContentType(): ContentType {
    switch (this.headers.get('content-type')) {
      case 'application/json':
        return ContentType.JSON;
      case 'application/x-www-form-urlencoded':
        return ContentType.FORM;
      case 'multipart/form-data':
        return ContentType.FORM_DATA;
      case 'text/plain':
      case 'text/html':
        return ContentType.TEXT;
      case 'application/octet-stream':
        return this._body instanceof ArrayBuffer ? ContentType.ARRAY_BUFFER : ContentType.BLOB;
      default:
        return this.detectContentTypeFromBody();
    }
  }

  /**
   * Returns the content type of request's body based on its type.
   */
  detectContentTypeFromBody(): ContentType {
    if (this._body == null) {
      return ContentType.NONE;
    } else if (this._body instanceof URLSearchParams) {
      return ContentType.FORM;
    } else if (this._body instanceof FormData) {
      return ContentType.FORM_DATA;
    } else if (this._body instanceof Blob) {
      return ContentType.BLOB;
    } else if (this._body instanceof ArrayBuffer) {
      return ContentType.ARRAY_BUFFER;
    } else if (this._body && typeof this._body === 'object') {
      return ContentType.JSON;
    } else {
      return ContentType.TEXT;
    }
  }

更新:

看起来它实际上可以通过扩展Request并重载detectContentType函数来返回0.这需要访问非公共代码,因为它可能在以后中断:

import {Http, Headers, RequestOptions, RequestMethod, Request, BaseRequestOptions, Response} from '@angular/http';
import { ContentType } from '@angular/http/src/enums';
import { RequestArgs } from '@angular/http/src/interfaces';

class NoContentRequest extends Request {
  constructor(args: RequestArgs) {
    super(args);
  }
  detectContentType(): ContentType {
    return 0;
  }
}

const headers = new Headers({Accept: 'application/json'});

const request  = new NoContentRequest({
  method: RequestMethod.Post,
  url: 'https://www.example.com/example',
  responseType: ResponseContentType.Json,
  headers: headers,
  body: body
});

this._http.request(request)
  .catch((error: Response | any) => { console.error(error); return Observable.throw(error); })
  .first()
  .subscribe();

我认为更好的方法是从请求中删除“Content-Type”标头。

     this.http.post(apiUrl, request, {
         headers: new HttpHeaders().delete('Content-Type')
     });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM