javascript - 我如何告诉 Angular 2 停止自动设置 Content-Type header ?

标签 javascript json laravel angular content-type

我目前正在尝试使用 Angular 2(通过 Ionic 2)应用访问 API。我们的 laravel 后端以这样一种方式设置,即它需要一个带有请求内容类型的 Accept header ,并且没有 Content-Type header 。不仅仅是一个空的 Content-Type header ,而是根本没有。

因此,我在 Http 中设置了必要的参数,在 header 中省略了 Content-Type,这就是问题开始的地方:Angular 2 显然不能将其手从 Content-Type 上移开。如果我给它一个对象作为请求的主体,它会将 Content-Type 设置为 application/json。这仍然是可以理解的。然后我将对象字符串化,这导致 Angular 将 Content-Type 设置为 text/plain。尝试,通过

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

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

或我能想象到的包含 application/json 的 Accept 的任何 header 的任何其他组合,即使 headers.set 或 headers.delete 失败,Angular 2 也会继续做它的事情。

在其他地方建议将 Content-Type 设置为 undefined,我也尝试将其设置为空字符串,在传入字符串化 JSON 时设置为 application/json,Angular 只是不给飞行 f...关于什么我想。有没有办法关闭这种自动化?我是否仍然做错了什么(我正在导入 header ,也就是缺少 header ,这是其他地方的问题,所以应该排除)?

代码如下:

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() 因为我发现在这种特殊情况下的 promise 更容易处理。

最佳答案

在深入研究 Angular 源代码后,我得出结论,这是不可能的。请参阅 static_request.ts ( https://github.com/angular/angular/blob/5293794316cc1b0f57d5d88b3fefdf6ae29d0d97/packages/http/src/static_request.ts ),它将首先检查您是否手动将 header 设置为特定字符串,未定义或空字符串将落入 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。这需要访问非公共(public)代码,但它可能会在未来中断:

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();

关于javascript - 我如何告诉 Angular 2 停止自动设置 Content-Type header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41448070/

相关文章:

java - 将 XML 字符串转换为 JSON 对象时删除前面的 0

php - 通过 ajax 或直接输出的行业标准代码 PHP 和 JSON 数据

php - Laravel 路由资源销毁不起作用

javascript - 为什么 {10 + '1' } + 10 等于 10?

javascript - Ember.js 框架可以在没有 Node.js 的情况下使用吗?

c# - 我应该如何处理 C# 到 JSON 序列化和循环引用?

mysql - Laravel 参数绑定(bind)导致偶尔出现 MySQL 一般错误

javascript - 带有垂直子菜单的水平响应式菜单

javascript - 标签焦点不改变css样式

php - 如何解决违反完整性约束的问题 : 1052 Column 'id' in where clause is ambiguous in laravel