54

I have an Ionic 2 application using Angular 2, which is sending an Http PUT to a ASP.NET Core API server. Here's the method I'm using to send the request:

public update(student: Student): Promise<Student>
{
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('authentication', `${student.token}`);

    const url = `${this.studentsUrl}`;

    return this.http
        .put(url, JSON.stringify(student), { headers: headers })
        .toPromise()
        .then(() => student)
        .catch(this.handleError);
}

I'm setting an authentication key/value on the headers object.

But when I receive this request on the server, I cannot find the authentication key on the header:

enter image description here

As you can see in the picture, there are many keys on the header, but not the content and authentication keys that I manually added to the header in the client application.

What am I doing wrong?

Zach Becknell
  • 61
  • 3
  • 8
rbasniak
  • 4,484
  • 11
  • 51
  • 100

7 Answers7

80

Your parameter for the request options in http.put() should actually be of type RequestOptions. Try something like this:

let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('authentication', `${student.token}`);

let options = new RequestOptions({ headers: headers });
return this.http
    .put(url, JSON.stringify(student), options)
Zach Becknell
  • 61
  • 3
  • 8
Paul Jerome Bordallo
  • 1,362
  • 10
  • 11
  • 8
    Type 'Headers' is not assignable to type 'Headers' :/ this does not work on angular 4 – elporfirio Jun 06 '17 at 15:15
  • 17
    It works, you just need the correct import for Headers: "import { Headers } from '@angular/http';" – Tim Jun 07 '17 at 13:52
  • 1
    I have imported import { Http, Response, RequestOptions, Headers } from '@angular/http'; , but unable to set headers in Angular 4 – Suvonkar Aug 31 '17 at 09:41
  • @Suvonkar see this from Angular doc: http .post('/api/items/add', body, { headers: new HttpHeaders().set('Authorization', 'my-auth-token'), }) .subscribe(); – Skyware Sep 05 '17 at 09:53
  • 1
    @elporfirio I have added an [answer for Angular 4](https://stackoverflow.com/a/46172188/1265945). – Brampage Sep 12 '17 at 09:07
  • @Suvonkar I have added an [anwer for Angular 4](https://stackoverflow.com/a/46172188/1265945). – Brampage Sep 13 '17 at 09:28
  • somehow this doesnt work. but without creating a variable but directly creating the object with in the http request does the trick for me, i dont why this happened – HexaCrop Apr 19 '19 at 10:01
64

Angular 4 >

You can either choose to set the headers manually, or make an HTTP interceptor that automatically sets header(s) every time a request is being made.


Manually

Setting a header:

http
  .post('/api/items/add', body, {
    headers: new HttpHeaders().set('Authorization', 'my-auth-token'),
  })
  .subscribe();

Setting headers:

this.http
.post('api/items/add', body, {
  headers: new HttpHeaders({
    'Authorization': 'my-auth-token',
    'x-header': 'x-value'
  })
}).subscribe()

Local variable (immutable instantiate again)

let headers = new HttpHeaders().set('header-name', 'header-value');
headers = headers.set('header-name-2', 'header-value-2');

this.http
  .post('api/items/add', body, { headers: headers })
  .subscribe()

The HttpHeaders class is immutable, so every set() returns a new instance and applies the changes.

From the Angular docs.


HTTP interceptor

A major feature of @angular/common/http is interception, the ability to declare interceptors which sit in between your application and the backend. When your application makes a request, interceptors transform it before sending it to the server, and the interceptors can transform the response on its way back before your application sees it. This is useful for everything from authentication to logging.

From the Angular docs.

Make sure you use @angular/common/http throughout your application. That way your requests will be catched by the interceptor.

Step 1, create the service:

import * as lskeys from './../localstorage.items';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';

@Injectable()
export class HeaderInterceptor implements HttpInterceptor {

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (true) { // e.g. if token exists, otherwise use incomming request.
            return next.handle(req.clone({
                setHeaders: {
                    'AuthenticationToken': localStorage.getItem('TOKEN'),
                    'Tenant': localStorage.getItem('TENANT')
                }
            }));
        }
        else {
            return next.handle(req);
        }
    }
}

Step 2, add it to your module:

providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HeaderInterceptor,
      multi: true // Add this line when using multiple interceptors.
    },
    // ...
  ]

Useful links:

Brampage
  • 6,014
  • 4
  • 33
  • 47
  • 1
    can you please write multiple key:value pair for header in 'Manually' part of your answer! Thanks! – Ankur Shah Nov 16 '17 at 07:53
  • 1
    @AnkurShah I have updated my answer, thanks for your feedback. – Brampage Nov 16 '17 at 08:21
  • When I am not using `HttpHeaders` the result is fine, but using it gives error as `TypeError: update.name.toLowerCase is not a function` !! ...and not fetching backend data! – Ankur Shah Nov 16 '17 at 08:30
  • Also, I am using a `get` request, with headers for token! – Ankur Shah Nov 16 '17 at 08:32
  • This should work I tested this answer. My suggestion would be to recreate a simple service from the ground up, using `@angular/common/http`. – Brampage Nov 16 '17 at 09:25
  • 1
    I'm sorry, its working now, I was still using `.set()`! Thanks again!....there is still an error which is coming due to late response, but that's a different issue! – Ankur Shah Nov 16 '17 at 11:03
  • Where is **localstorage.items**? I cannot use `import * as lskeys from './../localstorage.items'` – Jack Oct 06 '20 at 07:33
4

For us we used a solution like this:

this.http.get(this.urls.order + '&list', {
        headers: {
            'Cache-Control': 'no-cache',
        }
    }).subscribe((response) => { ...

Reference here

cjohansson
  • 1,058
  • 10
  • 13
3

We can do it nicely using Interceptors. You dont have to set options in all your services neither manage all your error responses, just define 2 interceptors (one to do something before sending the request to server and one to do something before sending the server's response to your service)

  1. Define an AuthInterceptor class to do something before sending the request to the server. You can set the api token (retrieve it from localStorage, see step 4) and other options in this class.

  2. Define an responseInterceptor class to do something before sending the server response to your service (httpClient). You can manage your server response, the most comon use is to check if the user's token is valid (if not clear token from localStorage and redirect to login).

  3. In your app.module import HTTP_INTERCEPTORS from '@angular/common/http'. Then add to your providers the interceptors (AuthInterceptor and responseInterceptor). Doing this your app will consider the interceptors in all our httpClient calls.

  4. At login http response (use http service), save the token at localStorage.

  5. Then use httpClient for all your apirest services.

You can check some good practices on my github proyect here

enter image description here

Daniel Delgado
  • 4,813
  • 5
  • 40
  • 48
2

This should be easily resolved by importing headers from Angular:

import { Http, Headers } from "@angular/http";
  • 2
    `@angular/http` is deprecated, and shoud not be used as of angular 4.3.x and above! Use `@angular/common/http` instead (look other answers)! – Ankur Shah Nov 16 '17 at 08:35
0

You have a typo.

Change: headers.append('authentication', ${student.token});

To: headers.append('Authentication', student.token);

NOTE the Authentication is capitalized

theCrab
  • 556
  • 5
  • 8
0

The simpler and current approach for adding header to a single request is:

// Step 1

const yourHeader: HttpHeaders = new HttpHeaders({
    Authorization: 'Bearer JWT-token'
});

// POST request

this.http.post(url, body, { headers: yourHeader });

// GET request

this.http.get(url, { headers: yourHeader });
Leon Grin
  • 889
  • 8
  • 10