Angular 4.3.3 HttpClient:如何从响应头中获取值?

IT技术 javascript angular typescript request typescript2.0
2021-01-19 14:43:02

(编辑器: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 角度文档

第一个问题是我有一个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的解决方案

6个回答

您可以观察完整的响应,而不仅仅是内容。为此,您必须传入函数调用observe: responseoptions参数。

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 的文档

好的,我刚刚发现:它是 http.patch(url, params, {observe: 'response'}) 并确保响应对象的类型为 HttpResponse<object>
2021-03-21 14:43:02
这对我来说太hacky了,如果这是让它工作的唯一方法,并且让它工作,这意味着它是可能的并且应该被集成到API中,我会将它报告为一个问题。
2021-03-23 14:43:02
谢谢!我得到了不受支持的数据类型,但这将是我的标头上的错误
2021-03-29 14:43:02
谢谢!我试过了,但我没有得到出现在Response Headers网络选项卡中的值。
2021-03-29 14:43:02
有没有人知道如何对 http.patch() 做同样的事情?它对我不起作用。当我想要带有状态代码的原始响应对象时,响应为空。
2021-04-02 14:43:02

类型转换的主要问题,因此我们可以使用“响应”作为“主体”

我们可以处理

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;
    });
我在这里有类似的问题stackoverflow.com/questions/61995994/...
2021-03-17 14:43:02
那个排版部分为我节省了很多时间和压力。谢谢辛格 (Y)
2021-03-27 14:43:02
很可能这个stackoverflow.com/questions/26329825/...仍然相关。
2021-04-01 14:43:02
我有一个变量“Set-Cookie”,我想访问它,它的值中有令牌。怎么做 ?
2021-04-12 14:43:02

事实上,主要问题是typescript问题。

在 post() 的代码中,选项直接在参数中声明,因此,作为“匿名”接口。

解决方案是将选项直接放在参数中的 raw 中

http.post("url", body, {headers: headers, observe: "response"}).subscribe...
@Gishu,这个答案中解释了原因一个对我来说非常有用的没有内联的解决方案是在这个答案中,尽管可能需要对界面进行一些更改以使其符合您的需要。
2021-03-25 14:43:02
救生员 - 这让我发疯了。仍然不明白为什么内联选项哈希有效但 post("url", body, options) 没有。但是耶!
2021-04-05 14:43:02
这应该有效,但在我这边不起作用,“post 方法”根本没有被调用,在这个设置中没有发送或接收任何东西,只有当我把 {observe: "response"} 作为第三个时它才有效范围
2021-04-12 14:43:02

如果您使用最佳答案中的解决方案并且您无权访问.keys().get()on response.headers,请确保您使用的是 fetch 而不是 xhr。

获取请求是默认的,但如果存在 xhr-only 标头(例如x-www-form-urlencoded,Angular 将使用 xhr

如果您尝试访问任何自定义响应标头,则必须使用另一个名为Access-Control-Expose-Headers 的标头指定这些标

下面的方法对我来说非常有效(目前是 Angular 10)。它还避免设置一些任意文件名,而是从内容处置标头中获取文件名。

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'));
})
这段代码可以更加module化,但你的答案正是我想要的
2021-03-14 14:43:02
我还没有用 Angular 8 尝试过,但我认为它会是一样的。也许有一个稍微不同的语法。@PawelCioch
2021-03-14 14:43:02
很高兴它对你有帮助:) @PawelCioch
2021-03-18 14:43:02
这么说,我有这个确切代码的问题(角度 8)我看不到标题,知道吗?API 返回 Content-Disposition 标头 100%,因为我对其进行了编码,而且我可以在浏览器请求调试/网络控制台中看到它
2021-03-26 14:43:02