简体   繁体   English

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

[英]Angular 4.3.3 HttpClient : How get value from the header of a response?

( Editor: VS Code; Typescript: 2.2.1 ) (编辑:VS Code;Typescript:2.2.1)

The purpose is to get the headers of the response of the request目的是获取请求响应的标头

Assume a POST request with HttpClient in a Service假设在服务中使用 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 HttpClient Angular 文档

The first problem is that I have a Typescript error:第一个问题是我有一个 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'

Indeed, when I go to the ref of post() method, I point on this prototype (I Use VS code)事实上,当我 go 到 post() 方法的引用时,我指向这个原型(我使用 VS 代码)

post(url: string, body: any | null, options: {
        headers?: HttpHeaders;
        observe?: 'body';
        params?: HttpParams;
        reportProgress?: boolean;
        responseType: 'arraybuffer';
        withCredentials?: boolean;
    }): Observable<ArrayBuffer>;

But I want this overloaded method:但我想要这个重载方法:

post(url: string, body: any | null, options: {
    headers?: HttpHeaders;
    observe: 'response';
    params?: HttpParams;
    reportProgress?: boolean;
    responseType?: 'json';
    withCredentials?: boolean;
}): Observable<HttpResponse<Object>>;

So, I tried to fix this error with this structure:所以,我试图用这个结构来修复这个错误:

  const options = {
            headers: headers,
            "observe?": "response",
            "responseType?": "json",
        };

And It compiles.它编译。 But I just get the body request as in json format.但我只收到 json 格式的正文请求。

Futhermore, why I have to put a?此外,为什么我必须放一个? symbol at the end of some name of fields?某些字段名称末尾的符号? As I saw on Typescript site, this symbol should just tell to the user that it is optional?正如我在 Typescript 网站上看到的那样,这个符号应该只是告诉用户它是可选的吗?

I also tried to use all the fields, without and with?我还尝试使用所有字段,没有和有? marks分数

EDIT编辑

I tried the solutions proposed by Angular 4 get headers from API response .我尝试了Angular 4 get headers from API response提出的解决方案。 For the map solution:对于 map 解决方案:

this.http.post(url).map(resp => console.log(resp));

Typescript compiler tells that map does not exists because it is not a part of Observable Typescript 编译器告诉我们 map 不存在,因为它不是 Observable 的一部分

I also tried this我也试过这个

import { Response } from "@angular/http";

this.http.post(url).post((resp: Response) => resp)

It compiles, but I get a unsupported Media Type response.它编译,但我得到一个不受支持的媒体类型响应。 These solutions should work for "Http" but it does not on "HttpClient".这些解决方案应该适用于“Http”,但不适用于“HttpClient”。

EDIT 2编辑 2

I get also a unsupported media type with the @Supamiu solution, so it would be an error on my headers.我还使用@Supamiu 解决方案获得了不受支持的媒体类型,因此这将是我的标头中的错误。 So the second solution from above (with Response type) should works too.因此,上面的第二个解决方案(使用 Response 类型)也应该有效。 But personnaly, I don't think it is a good way to mix "Http" with "HttpClient" so I will keep the solution of Supamiu但就个人而言,我不认为将“Http”与“HttpClient”混合使用是一种好方法,因此我将保留 Supamiu 的解决方案

You can observe the full response instead of the content only.您可以观察完整的响应,而不仅仅是内容。 To do so, you have to pass observe: response into the options parameter of the function call.为此,您必须将observe: response传递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);
  });

See HttpClient's documentation请参阅HttpClient 的文档

main problem of typecast so we can use "response" as 'body'类型转换的主要问题,因此我们可以使用“响应”作为“主体”

we can handle like我们可以处理

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

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.在 post() 的代码中,选项直接在参数中声明,因此,作为“匿名”接口。

The solution was to put directly the options in raw inside the parameters解决方案是将选项直接放在参数中的 raw 中

http.post("url", body, {headers: headers, observe: "response"}).subscribe...

If you use the solution from the top answer and you don't have access to .keys() or .get() on response.headers , make sure that you're using fetch rather than xhr.如果您使用从顶端应答解决方案,你没有访问.keys().get()response.headers ,请确保您使用的是获取,而不是XHR。

Fetch requests are the default, but Angular will use xhr if xhr-only headers are present (ex x-www-form-urlencoded ).获取请求是默认的,但如果存在 xhr-only 标头(例如x-www-form-urlencoded ),Angular 将使用 xhr。

If you are trying to access any custom response headers, then you have to specify those headers with another header called Access-Control-Expose-Headers .如果您尝试访问任何自定义响应标头,则必须使用另一个名为Access-Control-Expose-Headers 的标头指定这些标

The below method worked perfectly for me (currently Angular 10).下面的方法对我来说非常有效(目前是 Angular 10)。 It also avoids setting some arbitary filename, instead it gets the filename from the content-disposition header.它还避免设置一些任意文件名,而是从内容处置标头中获取文件名。

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'));
})

Some times even with the above solution you can't retrieve custom headers if it is CORS request.有时即使使用上述解决方案,如果是 CORS 请求,您也无法检索自定义标头。 In that case you need to whitelist desired headers in server side.在这种情况下,您需要在服务器端将所需的标头列入白名单。

For Example: Access-Control-Expose-Headers: X-Total-Count例如:Access-Control-Expose-Headers:X-Total-Count

As other developers said, for getting headers and body together you should define the type of observer yield in this way:正如其他开发人员所说,为了将标题和正文放在一起,您应该以这种方式定义观察者收益的类型:

http.post("url", body, {headers: headers, observe: "response" as "body"})

Then you can access to body and headers in pip or a subscribe area:然后您可以访问 pip 或订阅区域中的正文和标题:

http.post("url", body, {headers: headers, observe: "response" as "body"})
.pip(
  tap(res => {
   // res.headers
   // res.body
  })
)
.subscribe(res => {
   // res.headers
   // res.body
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM