Agregar un encabezado HTTP al Angular HttpClient no envía el encabezado, ¿por qué?

181

Aquí está mi 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.');
            }
        }
    );
}

y aquí la depuración de la red:

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

y los datos se almacenan en 'Solicitar carga útil' pero en mi servidor no recibió los valores POST:

print_r($_POST);
Array
(
)

Creo que el error proviene del encabezado no configurado durante la POST, ¿qué hice mal?

Frennetix
fuente
¡Si gracias! Pero después de no recibir datos en mi Back-end, fui a application / x-www-form-urlencoded. De todos modos, la pregunta principal es anserwerd
Frennetix
Consulte este ejemplo de HTTPClient de Angular 8 para consumir API RESTFul con encabezado personalizado y manejo de errores freakyjolly.com/…
Code Spy el

Respuestas:

310

Las instancias de la nueva HttpHeaderclase son objetos inmutables . Invocar métodos de clase devolverá una nueva instancia como resultado. Básicamente, debes hacer lo siguiente:

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

o

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

Actualización: agregar múltiples encabezados

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

o

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

Actualización: aceptar mapa de objetos para encabezados y parámetros HttpClient

Desde 5.0.0-beta.6 ahora es posible omitir la creación de un HttpHeadersobjeto y pasar directamente un mapa de objetos como argumento. Entonces ahora es posible hacer lo siguiente:

http.get('someurl',{
   headers: {'header1':'value1','header2':'value2'}
});
Jota.Toledo
fuente
50
Interesante. Entonces, para nosotros que venimos del mundo OO, el setnombre del método es algo engañoso.
tishma
3
¿Qué sucede si quiero configurar varios encabezados? ¿He tratado de encadenar el comentario HttpHeaders().set(..).set(..)pero ahora los encabezados no se escriben en los campos de encabezado HTTP?
mostrar el
Debería funcionar bien de acuerdo con src github.com/angular/angular/blob/master/packages/common/http/src/… . No puedo ayudarte más sin más información sobre tu problema (código)
Jota.Toledo
Entonces, en mi caso, cometí un error al cambiar encabezados y parámetros en la lista de argumentos a una función (ya que ambos aceptaron un objeto json). Es decir, solo tenga cuidado con los errores, y HttpHeaders como tipo es una buena práctica después de todo. Fuera de tema: cuando puede usar objetos en todas partes, no use TypeScript sino VanillaJS.
peligro89
3
¿Por qué los encabezados y las solicitudes se han hecho inmutables? angular.io/guide/http#immutability
Drellgor
23

Para agregar múltiples parámetros o encabezados, puede hacer lo siguiente:

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
fuente
1
Este método tampoco parece funcionar. Quiero decir, puede agregar los encabezados, y se mostrarán en la lazyUpdatepropiedad, pero eventualmente se bloqueará con la CreateListFromArrayLikeexcepción al hacer efectiva la solicitud suscribiéndose a ella.
Jago
3
Para agregar varios encabezados, use: encabezados: HttpHeaders = new HttpHeaders ({'Application-Id': this.appId, "REST-API-Key": this.apiKey, "Content-Type": "application / json"});
Benson
13

establecer encabezados http como a continuación en su solicitud http

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

Luché con esto durante mucho tiempo. Estoy usando Angular 6 y descubrí que

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

no funcionó. Pero lo que funcionó fue

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

hizo, lo que tiene sentido cuando te das cuenta de que son inmutables. Entonces, después de haber creado un encabezado que no puede agregarle. No lo he intentado, pero sospecho

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

funcionaría también

Martin Horton
fuente
Su primer intento debería funcionar, está asignando el resultado del anexo a la variable de encabezados. En este momento, su explicación no tiene ningún sentido, especialmente su última suposición de que agregar un let puede solucionarlo
Juan Mendes
3

Estaba con Angular 8 y lo único que funcionó para mí fue esto:

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

En el manual ( https://angular.io/guide/http ) leí: La clase HttpHeaders es inmutable, por lo que cada conjunto () devuelve una nueva instancia y aplica los cambios.

El siguiente código funciona para mí con angular-4:

 devuelva this.http.get (url, {encabezados: nuevos HttpHeaders (). set ('UserEmail', correo electrónico)});
Rob Lassche
fuente
0

En mi aplicación heredada, Array.from del prototipo js estaba en conflicto con Array.from de angular que causaba este problema. Lo resolví guardando la versión Array.from de angular y reasignándola después de la carga del prototipo.

Avinash Wable
fuente
-3

Ejemplo de Angular 8 HttpClient Service con manejo de errores y encabezado 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)
          )
      }

      ....
      ....

ingrese la descripción de la imagen aquí

Consulte el tutorial completo de ejemplo aquí

Code Spy
fuente
3
¿Soy yo o es un poco excesivo para la pregunta que se hace?
Ojonugwa Jude Ochalifu
3
Esto no intenta responder a la pregunta de los OP. Es solo un montón de código sin explicación alguna.
Jota.Toledo