(编辑:VS Code; Typescript:2.2.1)
目的是获取请求响应的标题
在服务
中假设使用HttpClient发出POST请求import {
Injectable
} from "@angular/core";
import {
HttpClient,
HttpHeaders,
} from "@angular/common/http";
@Injectable()
export class MyHttpClientService {
const url = 'url';
const body = {
body: 'the body'
};
const headers = 'headers made with HttpHeaders';
const options = {
headers: headers,
observe: "response", // to display the full response
responseType: "json"
};
return this.http.post(sessionUrl, body, options)
.subscribe(response => {
console.log(response);
return response;
}, err => {
throw err;
});
}
HttpClient Angular Documentation
第一个问题是我有一个Typescript错误:
'Argument of type '{
headers: HttpHeaders;
observe: string;
responseType: string;
}' is not assignable to parameter of type'{
headers?: HttpHeaders;
observe?: "body";
params?: HttpParams; reportProgress?: boolean;
respons...'.
Types of property 'observe' are incompatible.
Type 'string' is not assignable to type '"body"'.'
at: '51,49' source: 'ts'
的确,当我转到post()方法的参考时,我指向这个原型(我使用VS代码)
post(url: string, body: any | null, options: {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType: 'arraybuffer';
withCredentials?: boolean;
}): Observable<ArrayBuffer>;
但我想要这个重载方法:
post(url: string, body: any | null, options: {
headers?: HttpHeaders;
observe: 'response';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<HttpResponse<Object>>;
所以,我试图用这个结构修复这个错误:
const options = {
headers: headers,
"observe?": "response",
"responseType?": "json",
};
它编译!但我只是以json格式获取正文请求。
另外,为什么我要放一个?某些字段名称末尾的符号?正如我在Typescript网站上看到的那样,这个符号应该告诉用户它是可选的吗?
我还尝试使用所有字段,没有和有?标记
编辑
我尝试了Angular 4 get headers from API response提出的解决方案。对于地图解决方案:
this.http.post(url).map(resp => console.log(resp));
Typescript编译器告诉map不存在,因为它不是Observable的一部分
我也试过这个
import { Response } from "@angular/http";
this.http.post(url).post((resp: Response) => resp)
它编译,但我得到了不受支持的媒体类型响应。 这些解决方案应该适用于“Http”,但它不适用于“HttpClient”。
编辑2
我也使用@Supamiu解决方案获得了不受支持的媒体类型,因此我的标题会出错。所以上面的第二个解决方案(带响应类型)也应该有效。但是,我不认为将“Http”和“HttpClient”混合起来是一个很好的方法,所以我会保留Supamiu的解决方案
答案 0 :(得分:77)
您可以观察完整响应,而不仅仅是内容。为此,您必须将observe: response
传递给函数调用的options
参数。
http
.get<MyJsonData>('/data.json', {observe: 'response'})
.subscribe(resp => {
// Here, resp is of type HttpResponse<MyJsonData>.
// You can inspect its headers:
console.log(resp.headers.get('X-Custom-Header'));
// And access the body directly, which is typed as MyJsonData as requested.
console.log(resp.body.someField);
});
答案 1 :(得分:15)
类型转换的主要问题所以我们可以使用&#34;响应&#34;作为&#39; body&#39;
我们可以像
一样处理const options = {
headers: headers,
observe: "response" as 'body', // to display the full response & as 'body' for type cast
responseType: "json"
};
return this.http.post(sessionUrl, body, options)
.subscribe(response => {
console.log(response);
return response;
}, err => {
throw err;
});
答案 2 :(得分:13)
Indeed, the main problem was a Typescript problem.
In the code of post(), options was declared directly in the parameters, so, as an "anonymous" interface.
The solution was to put directly the options in raw inside the parameters
http.post("url", body, {headers: headers, observe: "response"}).subscribe...
答案 3 :(得分:1)
如果您使用的是顶部答案中的解决方案,并且您无权访问.keys()
上的.get()
或response.headers
,请确保您使用的是提取而不是xhr。
默认是获取请求,但是如果存在仅xhr的标头(例如x-www-form-urlencoded
),Angular将使用xhr。
如果您尝试访问任何自定义响应标头,则必须使用另一个名为Access-Control-Expose-Headers的标头来指定这些标头。
答案 4 :(得分:1)
以下方法对我来说非常有效(当前为Angular 10)。它还避免设置一些随意的文件名,而是从content-disposition标头获取文件名。
this._httpClient.get("api/FileDownload/GetFile", { responseType: 'blob' as 'json', observe: 'response' }).subscribe(response => {
/* Get filename from Content-Disposition header */
var filename = "";
var disposition = response.headers.get('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
// This does the trick
var a = document.createElement('a');
a.href = window.URL.createObjectURL(response.body);
a.download = filename;
a.dispatchEvent(new MouseEvent('click'));
})
答案 5 :(得分:0)
有时,即使使用上述解决方案,如果它是CORS请求,您也无法检索自定义标头。在这种情况下,您需要在服务器端将所需的标头列入白名单。
例如:Access-Control-Expose-Headers:X-Total-Count