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?


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

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

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

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


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

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

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.


-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í


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.