Angular 4.3.3 HttpClient:如何从响应的标头中获取值?
Posted
技术标签:
【中文标题】Angular 4.3.3 HttpClient:如何从响应的标头中获取值?【英文标题】:Angular 4.3.3 HttpClient : How get value from the header of a response? 【发布时间】:2018-01-12 07:44:25 【问题描述】:(编辑器:VS Code;打字稿:2.2.1)
目的是获取请求响应的headers
假设服务中带有 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() 方法的 ref 时,我指向了这个原型(我使用 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的解决方案
【问题讨论】:
Angular 4 get headers from API response的可能重复 @Hitmands 我已经看到了这个帖子,但是它使用 "Http" 而不是 "HttpClient" ,而 Angular 4.3.3 现在似乎倾向于使用 HttpClient 【参考方案1】:您可以观察完整的响应,而不仅仅是内容。为此,您必须将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);
);
见HttpClient's documentation
【讨论】:
谢谢!我得到了一个不受支持的数据类型,但这将是我的标题上的错误 有谁知道如何为 http.patch() 做同样的事情?它对我不起作用。当我想要带有状态码的原始响应对象时,响应为空。 好的,我刚刚发现:它是 http.patch(url, params, observe: 'response') 并确保响应对象的类型为 HttpResponse 谢谢!我试过了,但我没有得到出现在网络标签中Response Headers
中的值。
这对我来说太 hacky tbh,如果这是使它工作的唯一方法,并且使它工作,这意味着它是可能的并且应该集成到 API 中,我会报告它作为一个问题。【参考方案2】:
类型转换的主要问题,因此我们可以将“响应”用作“正文”
我们可以处理
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;
);
【讨论】:
那个排版部分为我节省了大量时间和压力。谢谢辛格(Y) 我有一个我想访问的变量“Set-Cookie”,它的值中有令牌。该怎么做? 我在这里有类似的问题***.com/questions/61995994/… 这个***.com/questions/26329825/… 很可能仍然相关。【参考方案3】:确实,主要问题是 Typescript 问题。
在 post() 的代码中,options 是直接在参数中声明的,所以,作为一个“匿名”接口。
解决方案是直接将选项放在参数里面
http.post("url", body, headers: headers, observe: "response").subscribe...
【讨论】:
救命稻草 - 这让我发疯了。仍然不明白为什么内联选项哈希有效但 post("url", body, options) 没有。但是耶! @Gishu,原因在this answer中解释。 this answer 是一个对我来说非常有用的无内联解决方案,尽管可能需要对界面进行一些更改以使其符合您的需要。 这应该可以工作,但它在我这边不起作用,“post 方法”根本没有被调用,在这个设置中没有发送或接收任何东西,它只有在我放 observe : "response" 作为第三个参数【参考方案4】:如果您使用最佳答案中的解决方案并且您无权访问 response.headers
上的 .keys()
或 .get()
,请确保您使用的是 fetch 而不是 xhr。
获取请求是默认的,但如果存在仅 xhr 的标头(例如 x-www-form-urlencoded
),Angular 将使用 xhr。
如果您尝试访问任何自定义响应标头,则必须使用另一个名为 Access-Control-Expose-Headers 的标头指定这些标头。
【讨论】:
【参考方案5】:以下方法对我来说非常有效(目前是 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'));
)
【讨论】:
这段代码可以更加模块化,但你的答案正是我想要的 很高兴它帮助了你:) @PawelCioch 这么说,我遇到的问题(角度 8)与这个确切的代码我看不到标题,知道吗? API 100% 返回 Content-Disposition 标头,因为我对其进行了编码,而且我可以在浏览器请求调试/网络控制台中看到它 我没有用 Angular 8 尝试过,但我认为它会是一样的。也许有一个稍微不同的语法。 @PawelCioch【参考方案6】:有时即使使用上述解决方案,如果是 CORS 请求,您也无法检索自定义标头。在这种情况下,您需要在服务器端将所需的标头列入白名单。
例如:Access-Control-Expose-Headers: X-Total-Count
【讨论】:
以上是关于Angular 4.3.3 HttpClient:如何从响应的标头中获取值?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Angular 将 Observable 用于 HttpClient?
如何从 Apache HttpClient 4.x 获取 cookie?