245

Here is my code:

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

and here the network debug:

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

and Data are stored in 'Request Payload' but in my server doesn't received the POST values:

print_r($_POST);
Array
(
)

I believe the error comes from the header not set during the POST, what did I do wrong?

Frennetix
  • 3,269
  • 5
  • 15
  • 23
  • Yes, thanks! But after not receiving data on my Back-end, I went to application/x-www-form-urlencoded. Anyway the main question is anserwerd – Frennetix Jul 31 '17 at 10:59

10 Answers10

413

The instances of the new HttpHeader class are immutable objects. Invoking class methods will return a new instance as result. So basically, you need to do the following:

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

or

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

Update: adding multiple headers

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

or

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

Update: accept object map for HttpClient headers & params

Since 5.0.0-beta.6 is now possible to skip the creation of a HttpHeaders object an directly pass an object map as argument. So now its possible to do the following:

http.get('someurl',{
   headers: {'header1':'value1','header2':'value2'}
});
Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
  • 68
    Interesting. So, for us coming from OO world, `set` method name is somewhat misleading. – tishma Sep 30 '17 at 09:45
  • 4
    What if I want to set multiple headers? I've tried to chain the comment `HttpHeaders().set(..).set(..)` but now again the headers are not getting written to the HTTP header fields?! – Stefan Falk Nov 02 '17 at 19:50
  • It should work fine according to the src https://github.com/angular/angular/blob/master/packages/common/http/src/headers.ts . I cant help you any further without more information about your issue (code) – Jota.Toledo Nov 02 '17 at 20:09
  • So in my case I made an mistake by switching headers & params in the list of arguments to a function (since both accepted a json object). Meaning just watch out for mistakes, and HttpHeaders as type is a good practice after all.. Off-topic: when you can use objects everywhere, don't use TypeScript but VanillaJS. – Melroy van den Berg Apr 26 '18 at 00:00
  • 4
    Why have headers and requests been made immutable? https://angular.io/guide/http#immutability – Drellgor May 23 '18 at 23:51
  • I am using Angular 6. After setting headers also, I am getting `Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:4200' is therefore not allowed access. The response had HTTP status code 403. properties.component.ts:23 GOT ERROR:-` on console. Can someone please suggest any solution? – hygull Jul 15 '18 at 16:47
  • I have already tried many methods. Changed the syntaxes of **HttpHeaders** values. Also checked angular.io. I am able to make API call and get the response if there is no AUTH. I am getting the above error in case of BASIC authentication. – hygull Jul 16 '18 at 02:23
  • As an important update, as of Angular 6.1.7, you cant use `.set()` either – mast3rd3mon Sep 10 '18 at 12:38
  • @mast3rd3mon Its still part of the public API https://angular.io/api/common/http/HttpHeaders#set – Jota.Toledo Sep 10 '18 at 13:01
  • @Jota.Toledo so is `.append()` but they only work when chained. `new HttpDeaders().set()` works but `let header = new HttpHeaders(); header.set()` doesnt – mast3rd3mon Sep 10 '18 at 13:04
  • @mast3rd3mon Both append and set return new instances with the changes applied, as I explain in my answer. How is that related to your previous comment? I think you should remove your comment, as you are making an incorrect assertion. – Jota.Toledo Sep 10 '18 at 16:10
  • @Jota.Toledo i wont remove my comment as it will help others, you either need to pass the headers into the HttpHeader constructor or call `.set()` or `.append()` directly from the `new HttpHeader()` – mast3rd3mon Sep 11 '18 at 08:10
  • lol thats exactly what I described in my answer. Whatever, just notice that "as of 6.1.7, you cant uset .set()" is an wrong assertion, or poorly explained. – Jota.Toledo Sep 11 '18 at 08:13
  • @Jota.Toledo ill rephrase, you cant use `.set()` and `.append()` without it being direct onto the constructor method – mast3rd3mon Sep 11 '18 at 08:17
  • 2
    Silly to make it not behave like https://developer.mozilla.org/en-US/docs/Web/API/Headers/append – Ruan Mendes Nov 14 '18 at 12:15
  • option _const headers = new HttpHeaders({'Content-Type':'application/json; charset=utf-8'});_ doesn't work, at least on Angular 9 my implementation : `let headers = new HttpHeaders().set('Content-Type','text/xml;charset=UTF-8').set...` – lyolikaa Apr 03 '20 at 16:47
30

To add multiples params or headers you can do the following:

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
    This method does not seem to work either. I mean, you can add the headers, and they will show in the `lazyUpdate` property, but eventually it will crash with the `CreateListFromArrayLike` exception when making the request effective by subscribing to it. – Jago Nov 14 '17 at 16:18
  • 3
    To add multiple headers use: headers:HttpHeaders = new HttpHeaders({ 'Application-Id': this.appId, "REST-API-Key": this.apiKey, "Content-Type": "application/json" }); – Benson Dec 12 '17 at 20:49
16

set http headers like below in your http request

return this.http.get(url, { headers: new HttpHeaders({'Authorization': 'Bearer ' + token})
 });
SherylHohman
  • 16,580
  • 17
  • 88
  • 94
rajamallareddys
  • 181
  • 1
  • 4
9

I struggled with this for a long time. I am using Angular 6 and I found that

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

did not work. But what did work was

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

did, which makes sense when you realize they are immutable. So having created a header you can't add to it. I haven't tried it, but I suspect

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

would work too.

Martin Horton
  • 822
  • 3
  • 10
  • 19
  • 2
    Your first attempt should work, you're assigning the result of the append to the headers variable. Right now your explanation doesn't make any sense, specially your last guess that adding a `let` *may* fix it – Ruan Mendes Nov 14 '18 at 12:45
8

I was with Angular 8 and the only thing which worked for me was this:

  getCustomHeaders(): HttpHeaders {
    const headers = new HttpHeaders()
      .set('Content-Type', 'application/json')
      .set('Api-Key', 'xxx');
    return headers;
  }
Raghav
  • 8,772
  • 6
  • 82
  • 106
5

In the manual (https://angular.io/guide/http) I read: The HttpHeaders class is immutable, so every set() returns a new instance and applies the changes.

The following code works for me with angular-4:

 return this.http.get(url, {headers: new HttpHeaders().set('UserEmail', email ) });
Rob Lassche
  • 841
  • 10
  • 16
5

First, you need to add HttpHeaders with HttpClient

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

your constructor should be like this.

constructor(private http: HttpClient) { }

then you can use like this

   let header = new HttpHeaders({ "Authorization": "Bearer "+token});

   const requestOptions = {  headers: header};                                                                                                                                                                            

    return this.http.get<any>(url, requestOptions)
        .toPromise()
        .then(data=> {
            //...
            return data;
    });
Ramazan Zülkarneyn
  • 153
  • 1
  • 4
  • 14
0

In my legacy app Array.from of prototype js was conflicting with angular's Array.from that was causing this problem. I resolved it by saving angular's Array.from version and reassigning it after prototype load.

Avinash Wable
  • 91
  • 1
  • 1
  • 5
0

I was struggling with this as well. I used an interceptor, it captures the response headers, then clone the headers(since headers are immutable objects) and then sends the modified headers. https://angular.io/guide/http#intercepting-requests-and-responses

chaimite
  • 114
  • 13
-2

Angular 8 HttpClient Service example with Error Handling and Custom Header

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

      ....
      ....

enter image description here

Check complete example tutorial here

Code Spy
  • 9,626
  • 4
  • 66
  • 46