Добавление заголовка HTTP к Angular 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

и данные хранятся в «Request Payload», но на моем сервере не получены значения POST:

print_r($_POST);
Array
(
)

Я полагаю, что ошибка происходит из-за заголовка, не установленного во время POST, что я сделал не так?

Frennetix
источник
Да, спасибо! Но после того, как я не получил данные на своем Back-end, я пошел в application / x-www-form-urlencoded. Во всяком случае, главный вопрос - anserwerd
Frennetix
Проверьте этот пример Angular 8 HTTPClient, чтобы использовать RESTFul API с пользовательским заголовком и обработкой ошибок freakyjolly.com/…
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-бета.6 теперь можно пропустить создание HttpHeadersобъекта и напрямую передать карту объекта в качестве аргумента. Так что теперь можно сделать следующее:

http.get('someurl',{
   headers: {'header1':'value1','header2':'value2'}
});
Jota.Toledo
источник
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.
danger89
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 })
Хэллисон Энрике
источник
2
Этот метод, похоже, тоже не работает. Я имею в виду, что вы можете добавить заголовки, и они будут отображаться в lazyUpdateсвойстве, но в конечном итоге это приведет к сбою, за CreateListFromArrayLikeисключением случаев, когда запрос будет эффективным при подписке на него.
Яго
3
Чтобы добавить несколько заголовков, используйте: headers: HttpHeaders = new HttpHeaders ({'Application-Id': this.appId, "REST-API-Key": this.apiKey, "Content-Type": "application / json"});
Бенсон
13

установите заголовки http как показано ниже в вашем запросе http

return this.http.get(url, { headers: new HttpHeaders({'Authorization': 'Bearer ' + token})
 });
rajamallareddys
источник
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');

будет работать тоже.

Мартин Хортон
источник
Ваша первая попытка должна сработать, вы присваиваете результат добавления к переменной headers. Прямо сейчас ваше объяснение не имеет никакого смысла, особенно ваше последнее предположение, что добавление let может исправить это
Хуан Мендес
3

Я был с Angular 8, и единственное, что сработало для меня, это:

  getCustomHeaders(): HttpHeaders {
    const headers = new HttpHeaders()
      .set('Content-Type', 'application/json')
      .set('Api-Key', 'xxx');
    return headers;
  }
Raghav
источник
2

В руководстве ( https://angular.io/guide/http ) я прочитал: класс HttpHeaders является неизменным, поэтому каждый set () возвращает новый экземпляр и применяет изменения.

Следующий код работает для меня с angular-4:

 вернуть this.http.get (url, {headers: new HttpHeaders (). set ('UserEmail', email)});
Роб Ласше
источник
0

В моем устаревшем приложении Array.from из прототипа js конфликтовал с Array.from из angular, который вызывал эту проблему. Я решил это, сохранив версию Angray Array.from и переназначив ее после загрузки прототипа.

Avinash Wable
источник
-3

Пример службы HttpClient Angular 8 с обработкой ошибок и пользовательским заголовком

    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
Это я или это своего рода излишество за заданный вопрос?
Оджонугва Джуд Очалифу
3
Это не попытка ответить на вопрос ОП. Это просто набор кода без каких-либо объяснений.
Jota.Toledo