73 votes

Angular 4.3.3 HttpClient : Comment obtenir la valeur de l'en-tête d'une réponse ?

( Editeur: VS Code; Typescript: 2.2.1 )

Le but est d'obtenir les en-têtes de la réponse de la requête

Supposons une requête POST avec HttpClient dans un service

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

Documentation HttpClient Angular

Le premier problème est que j'ai une erreur de Typescript :

'Argument de type '{ 
    headers: HttpHeaders; 
    observe: string; 
    responseType: string;
}' n'est pas assignable au paramètre de type '{ 
    headers?: HttpHeaders;
    observe?: "body";
    params?: HttpParams; reportProgress?: boolean;
    respons...'.

Types de propriété 'observe' sont incompatibles.
Le type 'string' n'est pas assignable au type '"body"'.'
à: '51,49' source: 'ts'

En effet, lorsque je vais à la référence de la méthode post(), je pointe sur ce prototype (j'utilise VS code)

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

Mais je veux cette méthode surchargée :

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

Donc, j'ai essayé de corriger cette erreur avec cette structure :

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

Et ça compile ! Mais je reçois simplement le corps de la requête au format json.

En outre, pourquoi dois-je mettre un symbole ? à la fin de certains noms de champs ? Comme je l'ai vu sur le site Typescript, ce symbole devrait simplement indiquer à l'utilisateur qu'il est facultatif ?

J'ai également essayé d'utiliser tous les champs, sans et avec des ?

EDIT

J'ai essayé les solutions proposées par Angular 4 obtenir les en-têtes de la réponse API. Pour la solution map :

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

Le compilateur Typescript indique que map n'existe pas car ce n'est pas une partie de Observable

J'ai aussi essayé ceci

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

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

Ça compile, mais je reçois une réponse de type support non pris en charge. Ces solutions devraient fonctionner pour "Http" mais pas sur "HttpClient".

EDIT 2

J'obtiens également une réponse de type de support non pris en charge avec la solution @Supamiu, donc il y aurait une erreur sur mes en-têtes. Donc la deuxième solution ci-dessus (avec le type Response) devrait aussi fonctionner. Mais personnellement, je ne pense pas que ce soit une bonne façon de mélanger "Http" avec "HttpClient" donc je vais garder la solution de Supamiu

0 votes

3 votes

@Hitmands J'ai déjà vu ce fil de discussion, cependant il utilise "Http" et non pas "HttpClient", et Angular 4.3.3 semble tendre à utiliser HttpClient maintenant.

145voto

Supamiu Points 5927

Vous pouvez observer la réponse complète au lieu du contenu uniquement. Pour ce faire, vous devez transmettre observe: response dans le paramètre options de l'appel de la fonction.

http
  .get('/data.json', {observe: 'response'})
  .subscribe(resp => {
    // Ici, resp est de type HttpResponse.
    // Vous pouvez inspecter ses en-têtes :
    console.log(resp.headers.get('X-Custom-Header'));
    // Et accéder directement au corps, qui est typé comme MyJsonData comme demandé.
    console.log(resp.body.someField);
  });

Voir la documentation de HttpClient

0 votes

Merci! Je reçois un type de données non pris en charge mais ce serait une erreur de ma part dans les en-têtes

0 votes

Est-ce que quelqu'un a une idée de comment faire la même chose pour http.patch() ? Ça ne fonctionne pas pour moi. La réponse est vide, alors que je voudrais avoir l'objet de réponse brut avec un code de statut.

0 votes

D'accord, je viens de découvrir : c'est http.patch(url, params, {observe: 'response'}) et assurez-vous que l'objet de réponse est de type HttpResponse

28voto

Birbal Singh Points 618

Principal problème de typecast donc nous pouvons utiliser "response" comme 'body'

nous pouvons gérer comme

const options = {
    headers: headers,
    observe: "response" as 'body', // pour afficher la réponse complète & comme 'body' pour le type cast
    responseType: "json"
};

return this.http.post(sessionUrl, body, options)
    .subscribe(response => {
        console.log(response);
        return response;
    }, err => {
        throw err;
    });

0 votes

Cette partie de typage m'a fait gagner beaucoup de temps et de tension. Merci Singh (Y)

0 votes

J'ai une variable 'Set-Cookie' à laquelle je veux accéder, qui contient un jeton dans sa valeur. Comment faire ?

0 votes

J'ai une question similaire ici stackoverflow.com/questions/61995994/…

15voto

M.Lobry Points 455

En effet, le principal problème était un problème de Typescript.

Dans le code de post(), les options étaient déclarées directement dans les paramètres, donc, en tant qu'interface "anonyme".

La solution a été de mettre directement les options en brut à l'intérieur des paramètres

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

2 votes

Life saver - cela me rendait fou. Je ne comprends toujours pas pourquoi l'encapsulation de l'option hash fonctionne mais pas post("url", corps, options). Mais hourra!

1 votes

@Gishu, la raison est expliquée dans cette réponse. Une solution qui a bien fonctionné pour moi sans l'inline est présentée dans cette réponse, bien que quelques changements puissent être nécessaires pour adapter l'interface à vos besoins.

0 votes

Cela devrait fonctionner, mais cela ne fonctionne pas de mon côté, la "méthode post" n'est tout simplement pas appelée, rien n'est envoyé ou reçu dans cette configuration, cela ne fonctionne que si je mets {observe: "response"} comme 3ème paramètre

2voto

Anokrize Points 429

La méthode ci-dessous a parfaitement fonctionné pour moi (actuellement Angular 10). Elle évite également de définir un nom de fichier arbitraire, à la place elle récupère le nom de fichier à partir de l'en-tête content-disposition.

this._httpClient.get("api/FileDownload/GetFile", { responseType: 'blob' as 'json', observe: 'response' }).subscribe(response =>  { 
    /* Obtenir le nom de fichier à partir de l'en-tête Content-Disposition */
    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, '');
    }
    // Cela fait l'affaire
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(response.body);
    a.download = filename;
    a.dispatchEvent(new MouseEvent('click'));
})

2voto

Kevin Beal Points 1078

Si vous utilisez la solution de la réponse principale et que vous n'avez pas accès à .keys() ou .get() sur response.headers, assurez-vous d'utiliser fetch plutôt que xhr.

Les requêtes Fetch sont les paramètres par défaut, mais Angular utilisera xhr si des en-têtes xhr-only sont présents (par exemple x-www-form-urlencoded).

Si vous essayez d'accéder à des en-têtes de réponse personnalisés, vous devez spécifier ces en-têtes avec un autre en-tête appelé Access-Control-Expose-Headers.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X