Додавання заголовка HTTP до кутового HttpClient не надсилає заголовок, чому?


181

Ось мій код:

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

і ось мережа налагодження:

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

і Дані зберігаються у "Запит корисної навантаження", але на моєму сервері не отримано значення POST:

print_r($_POST);
Array
(
)

Я вважаю, що помилка приходить із заголовка, не встановленого під час POST, що я зробив неправильно?


Так дякую! Але після отримання даних про мій бек-енд я перейшов до application / x-www-form-urlencoded. Як би то не було, головне питання
Fsernetix"

Перевірте цей приклад Angular 8 HTTPClient, щоб споживати API RESTFul зі спеціальним заголовком та обробкою
Code Spy

Відповіді:


311

Екземпляри нового HttpHeaderкласу - це незмінні об'єкти. Методи класу виклику повернуть новий результат як результат. Отже, вам потрібно зробити наступне:

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

або

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

Оновлення: додавання декількох заголовків

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

або

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

Оновлення: прийняти карту об'єктів для заголовків та парам HttpClient

Оскільки 5.0.0-beta.6 тепер можна пропустити створення HttpHeadersоб'єкта, безпосередньо передати об'єктну карту як аргумент. Тож тепер можна зробити наступне:

http.get('someurl',{
   headers: {'header1':'value1','header2':'value2'}
});

50
Цікаво. Отже, для нас, що походять із світу OO, setназва методу дещо вводить в оману.
тишма

3
Що робити, якщо я хочу встановити кілька заголовків? Я спробував зав'язати коментар, HttpHeaders().set(..).set(..)але тепер знову заголовки не записуються в поля заголовка HTTP ?!
displayname

Він повинен працювати нормально відповідно до src github.com/angular/angular/blob/master/packages/common/http/src/… . Я не можу вам більше допомогти без додаткової інформації про вашу проблему (код)
Jota.Toledo

Тож у моєму випадку я помилився, переключивши заголовки та параметри у списку аргументів на функцію (оскільки обидва прийняли об’єкт json). Значить просто слідкуйте за помилками, а HttpHeaders як тип - це найкраща практика зрештою .. Поза темою: коли ви можете використовувати об'єкти скрізь, не використовуйте TypeScript, а VanillaJS.
небезпека89

3
Чому заголовки та запити стали незмінними? angular.io/guide/http#immutability
Дрелгор

23

Щоб додати кілька парам або заголовків, ви можете зробити наступне:

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
Цей метод, здається, також не працює. Я маю на увазі, ви можете додати заголовки, і вони відображатимуться у lazyUpdateвласності, але врешті-решт він вийде з ладу за CreateListFromArrayLikeвинятком, коли зробити запит ефективним, підписавшись на нього.
Jago

3
Для додавання кількох заголовків використовуйте: заголовки: HttpHeaders = нові HttpHeaders ({'Application-Id': this.appId, "REST-API-ключ": this.apiKey, "Content-Type": "application / json"});
Бенсон

13

встановіть заголовки http, як показано нижче, у своєму запиті http

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

5

Я довго боровся з цим. Я використовую Angular 6, і я виявив це

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

не працює. Але те, що було, працювало

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

зробив, що має сенс, коли ти розумієш, що вони незмінні. Тож створивши заголовок, ви не можете до нього додати. Я не пробував цього, але підозрюю

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

працював би теж.


Ваша перша спроба повинна спрацювати, ви присвоюєте результат додавання до змінної заголовків. Наразі ваше пояснення не має сенсу, особливо Ваша остання здогадка, що додавання let може виправити це
Хуан Мендес

3

Я був з Angular 8, і єдине, що працювало для мене, це:

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

2

У посібнику ( https://angular.io/guide/http ) я читав: Клас HttpHeaders є незмінним, тому кожен набір () повертає новий екземпляр і застосовує зміни.

Наступний код працює для мене з кутом-4:

 повернути this.http.get (url, {headers: new HttpHeaders (). set ('UserEmail', email)});

0

У моєму застарілому додатку Array.from прототипу js конфліктував з кутовим Array.from, який спричиняв цю проблему. Я вирішив це, зберегши версію Array.from від angular і перепризначивши її після завантаження прототипу.


-3

Приклад кутового сервісу 8 HttpClient з обробкою помилок та спеціальним заголовком

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

      ....
      ....

введіть тут опис зображення

Перевірте повний приклад навчального посібника тут


3
Це я чи це щось надмірне на запитання?
Ojonugwa Jude Ochalifu

3
Це не намагається відповісти на питання ОП. Це просто купа коду без жодних пояснень.
Jota.Toledo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.