簡體   English   中英

Angular 4.3.3 HttpClient:如何從響應的 header 中獲取值?

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

(編輯: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 文檔

第一個問題是我有一個 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'

事實上,當我 go 到 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提出的解決方案。 對於 map 解決方案:

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 解決方案獲得了不受支持的媒體類型,因此這將是我的標頭中的錯誤。 因此,上面的第二個解決方案(使用 Response 類型)也應該有效。 但就個人而言,我不認為將“Http”與“HttpClient”混合使用是一種好方法,因此我將保留 Supamiu 的解決方案

您可以觀察完整的響應,而不僅僅是內容。 為此,您必須將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);
  });

請參閱HttpClient 的文檔

類型轉換的主要問題,因此我們可以使用“響應”作為“主體”

我們可以處理

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

事實上,主要問題是打字稿問題。

在 post() 的代碼中,選項直接在參數中聲明,因此,作為“匿名”接口。

解決方案是將選項直接放在參數中的 raw 中

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

如果您使用從頂端應答解決方案,你沒有訪問.keys().get()response.headers ,請確保您使用的是獲取,而不是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'));
})

有時即使使用上述解決方案,如果是 CORS 請求,您也無法檢索自定義標頭。 在這種情況下,您需要在服務器端將所需的標頭列入白名單。

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

正如其他開發人員所說,為了將標題和正文放在一起,您應該以這種方式定義觀察者收益的類型:

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

然后您可以訪問 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