Adicionar um cabeçalho HTTP ao Angular HttpClient não envia o cabeçalho, por quê?

181

Aqui está o meu código:

import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';

logIn(username: string, password: string) {
    const url = 'http://server.com/index.php';
    const body = JSON.stringify({username: username,
                                 password: password});
    const headers = new HttpHeaders();
    headers.set('Content-Type', 'application/json; charset=utf-8');
    this.http.post(url, body, {headers: headers}).subscribe(
        (data) => {
            console.log(data);
        },
        (err: HttpErrorResponse) => {
            if (err.error instanceof Error) {
                console.log('Client-side error occured.');
            } else {
                console.log('Server-side error occured.');
            }
        }
    );
}

e aqui a rede depura:

Request Method:POST
Status Code:200 OK
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:46
Content-Type:text/plain

e Dados são armazenados em 'Solicitar carga útil', mas no meu servidor não recebeu os valores POST:

print_r($_POST);
Array
(
)

Acredito que o erro vem do cabeçalho não definido durante o POST, o que fiz de errado?

Frennetix
fonte
Sim obrigado! Mas, depois de não receber dados no meu back-end, fui para application / x-www-form-urlencoded. De qualquer forma, a questão principal é anserwerd
Frennetix
Marque esta Angular 8 HTTPClient exemplo para consumir API RESTful com cabeçalho personalizado e tratamento de erros freakyjolly.com/...
Code Spy

Respostas:

310

As instâncias da nova HttpHeaderclasse são objetos imutáveis . Invocar métodos de classe retornará uma nova instância como resultado. Então, basicamente, você precisa fazer o seguinte:

let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json; charset=utf-8');

ou

const headers = new HttpHeaders({'Content-Type':'application/json; charset=utf-8'});

Atualização: adicionando vários cabeçalhos

let headers = new HttpHeaders();
headers = headers.set('h1', 'v1').set('h2','v2');

ou

const headers = new HttpHeaders({'h1':'v1','h2':'v2'});

Atualização: aceite o mapa de objetos para cabeçalhos e parâmetros de HttpClient

Desde 5.0.0-beta.6 agora é possível pular a criação de um HttpHeadersobjeto e passar diretamente um mapa de objeto como argumento. Então agora é possível fazer o seguinte:

http.get('someurl',{
   headers: {'header1':'value1','header2':'value2'}
});
Jota.Toledo
fonte
50
Interessante. Portanto, para nós provenientes do mundo OO, o setnome do método é um pouco enganador.
Tishma
3
E se eu quiser definir vários cabeçalhos? Eu tentei encadear o comentário, HttpHeaders().set(..).set(..)mas agora novamente os cabeçalhos não estão sendo gravados nos campos do cabeçalho HTTP ?!
displayname
Ele deve funcionar bem de acordo com o src github.com/angular/angular/blob/master/packages/common/http/src/… . Eu não posso ajudá-lo mais, sem mais informações sobre o problema (código)
Jota.Toledo
Portanto, no meu caso, cometi um erro ao alternar cabeçalhos e parâmetros na lista de argumentos para uma função (já que ambos aceitaram um objeto json). O significado é apenas observar os erros, e o HttpHeaders como tipo é uma boa prática, afinal. Fora do tópico: quando você pode usar objetos em qualquer lugar, não use o TypeScript, mas o VanillaJS.
danger89
3
Por que cabeçalhos e solicitações foram imutáveis? angular.io/guide/http#immutability
Drellgor 23/05
23

Para adicionar múltiplos parâmetros ou cabeçalhos, você pode fazer o seguinte:

constructor(private _http: HttpClient) {}

//....

const url = `${environment.APP_API}/api/request`;

let headers = new HttpHeaders().set('header1', hvalue1); // create header object
headers = headers.append('header2', hvalue2); // add a new header, creating a new object
headers = headers.append('header3', hvalue3); // add another header

let params = new HttpParams().set('param1', value1); // create params object
params = params.append('param2', value2); // add a new param, creating a new object
params = params.append('param3', value3); // add another param 

return this._http.get<any[]>(url, { headers: headers, params: params })
Hallyson Henrique
fonte
1
Este método também não parece funcionar. Quero dizer, você pode adicionar os cabeçalhos, e eles serão exibidos na lazyUpdatepropriedade, mas, eventualmente, ele trava com a CreateListFromArrayLikeexceção ao tornar a solicitação efetiva, assinando-a.
Jago
3
Para adicionar vários cabeçalhos, use: headers: HttpHeaders = new HttpHeaders ({'Application-Id': this.appId, "REST-API-Key": this.apiKey, "Content-Type": "application / json"});
Benson
13

defina cabeçalhos http como abaixo em sua solicitação http

return this.http.get(url, { headers: new HttpHeaders({'Authorization': 'Bearer ' + token})
 });
rajamallareddys
fonte
5

Eu lutei com isso por um longo tempo. Estou usando o Angular 6 e descobri que

let headers = new HttpHeaders();
headers = headers.append('key', 'value');

não funcionou. Mas o que funcionou foi

let headers = new HttpHeaders().append('key', 'value');

fez, o que faz sentido quando você percebe que eles são imutáveis. Então, depois de criar um cabeçalho, você não pode adicioná-lo. Eu não tentei, mas suspeito

let headers = new HttpHeaders();
let headers1 = headers.append('key', 'value');

funcionaria também.

Martin Horton
fonte
Sua primeira tentativa deve funcionar, você está atribuindo o resultado do acréscimo à variável de cabeçalhos. Agora a sua explicação não faz qualquer sentido, especialmente sua última suposição de que a adição de um let pode corrigi-lo
Juan Mendes
3

Eu estava com o Angular 8 e a única coisa que funcionou para mim foi esta:

  getCustomHeaders(): HttpHeaders {
    const headers = new HttpHeaders()
      .set('Content-Type', 'application/json')
      .set('Api-Key', 'xxx');
    return headers;
  }
Raghav
fonte
2

No manual ( https://angular.io/guide/http ), li: A classe HttpHeaders é imutável; portanto, cada set () retorna uma nova instância e aplica as alterações.

O código a seguir funciona para mim com angular-4:

 retorne this.http.get (url, {headers: new HttpHeaders (). set ('UserEmail', email)});
Rob Lassche
fonte
0

No meu aplicativo herdado, Array.from do protótipo js estava em conflito com o Array.from da angular, que estava causando esse problema. Eu o resolvi salvando a versão Array.from da angular e reatribuindo-a após o carregamento do protótipo.

Avinash Wable
fonte
-3

Exemplo de serviço HttpClient angular 8 com tratamento de erros e cabeçalho personalizado

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
    import { Student } from '../model/student';
    import { Observable, throwError } from 'rxjs';
    import { retry, catchError } from 'rxjs/operators';

    @Injectable({
      providedIn: 'root'
    })
    export class ApiService {

      // API path
      base_path = 'http://localhost:3000/students';

      constructor(private http: HttpClient) { }

      // Http Options
      httpOptions = {
        headers: new HttpHeaders({
          'Content-Type': 'application/json'
        })
      }

      // Handle API errors
      handleError(error: HttpErrorResponse) {
        if (error.error instanceof ErrorEvent) {
          // A client-side or network error occurred. Handle it accordingly.
          console.error('An error occurred:', error.error.message);
        } else {
          // The backend returned an unsuccessful response code.
          // The response body may contain clues as to what went wrong,
          console.error(
            `Backend returned code ${error.status}, ` +
            `body was: ${error.error}`);
        }
        // return an observable with a user-facing error message
        return throwError(
          'Something bad happened; please try again later.');
      };


      // Create a new item
      createItem(item): Observable<Student> {
        return this.http
          .post<Student>(this.base_path, JSON.stringify(item), this.httpOptions)
          .pipe(
            retry(2),
            catchError(this.handleError)
          )
      }

      ....
      ....

insira a descrição da imagem aqui

Veja o exemplo completo do tutorial aqui

Code Spy
fonte
3
Sou eu ou isso é um exagero para a pergunta?
Ojonugwa Jude Ochalifu
3
Isso não está tentando responder à pergunta dos OPs. É apenas um monte de código sem explicação alguma.
Jota.Toledo