我目前正在尝试使用Angular 2(通过Ionic 2)应用程序访问API。我们的laravel后端设置为这样一种方式,即它期望带有请求内容类型的Accept标头,而没有Content-Type标头。不仅是一个空的Content-Type标头,而且根本没有。
因此,我在Http中设置了必需的参数,而在Headers中省略了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);
或任何其他我可以想象包含Header接受application / json的标头的任何其他组合,即使headers.set或headers.delete失败,Angular 2也会继续做它的事情。
在其他地方建议将Content-Type设置为undefined,我还尝试将其设置为空字符串,并在传入字符串化JSON时将其设置为application / json,Angular并没有给出想要的信息。有没有办法关闭这种自动功能?我还在做错什么吗(我正在导入Headers,也就是缺少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(),因为我发现在这种特殊情况下更容易处理承诺。
深入研究Angular源代码后,我得出结论认为这是不可能的。参见static_request.ts(https://github.com/angular/angular/blob/5293794316cc1b0f57d5d88b3fefdf6ae29d0d97/packages/http/src/static_request.ts),它将首先检查您是否已将标题手动设置为特定字符串,并且未定义或空字符串将落入detectContentTypeFromBody函数,该函数仅在您的请求正文为null时设置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();
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句