web-dev-qa-db-ja.com

Angular 4.3.3 HttpClient:応答のヘッダーから値を取得する方法

(エディター: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()メソッドの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はAPI応答からヘッダーを取得 によって提案されたソリューションを試しました。マップソリューションの場合:

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

TypeScriptコンパイラは、Observableの一部ではないためマップが存在しないことを通知します

私もこれを試しました

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

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

コンパイルはされますが、サポートされていないメディアタイプの応答が返されます。これらのソリューションは「Http」では機能するはずですが、「HttpClient」では機能しません。

EDIT 2

@Supamiuソリューションでサポートされていないメディアタイプも取得するため、ヘッダーでエラーになります。したがって、上記の2番目のソリューション(応答タイプを使用)も機能するはずです。しかし、個人的には、「Http」と「HttpClient」を混在させるのは良い方法ではないと思うので、Supamiuのソリューションを維持します。

41
M.Lobry

コンテンツのみではなく、完全な応答を確認できます。そのためには、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のドキュメント を参照してください

84
Supamiu

タイプキャストの主な問題なので、「応答」を「ボディ」として使用できます

私たちは

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;
    });
15
Birbal Singh

実際、主な問題はTypeScriptの問題でした。

Post()のコードでは、オプションはパラメーターで直接宣言されているため、「匿名」インターフェースとして使用されます。

解決策は、オプションを直接パラメーター内のrawに配置することでした

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

一番上の回答のソリューションを使用し、response.headers.keys()または.get()にアクセスできない場合は、xhrではなくfetchを使用していることを確認してください。

取得リクエストはデフォルトですが、Angularは、xhrのみのヘッダーが存在する場合はxhrを使用します(例:x-www-form-urlencoded)。

カスタムレスポンスヘッダーにアクセスしようとしている場合は、 Access-Control-Expose-Headers と呼ばれる別のヘッダーでそれらのヘッダーを指定する必要があります。

1
Kevin Beal