Ionic Http appending header


#1

Hi Everyone,
I have started an app using the super star template. S far the template proved to be quite cool. Most of what was needed was already handled. The template is a great boiler plate for starting an app.
However there this part in api.ts where the initial design has already given different methods to utilize. Post get put delete etc… now in each method takes a reOpts variable which basically gives an options to send specific headers of params. I have a requirement that in some calls I need to append to header the authorization token. to keep the design clean I followed the structure that was followed initially in the template.
So I have a provider for my Trips page

import 'rxjs/add/operator/toPromise';

import { Injectable } from '@angular/core';

import { Api } from '../api/api';

import { NativeStorage } from '@ionic-native/native-storage';

@Injectable()
export class Tripserv {
  news:any;
  subSegment:any;
  subSegmentEmployee:any;
  constructor(public api: Api) { 
    this.subSegment = 'trips/';
    this.subSegmentEmployee = 'employees/trips/requests/'
  }
  listTrips(){
    let seq = this.api.get(this.subSegment+'list').share();
    return seq;
  }
  submitTrips(body){
    let reqOpts;
    reqOpts = this.api._initializeReqOpts(reqOpts);
    reqOpts = this.api._addStandardHeaders(reqOpts.headers);
    let seq = this.api.post(this.subSegmentEmployee+'save',body,reqOpts).share();
    return seq;
  }
}

Then there is the api.ts file which carries all the methods so that it can be reused in other providers.

import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
  import { RequestOptions } from '@angular/http';
import { Injectable } from '@angular/core';

/**
 * Api is a generic REST Api handler. Set your API url first.
 */
@Injectable()
export class Api {
  url: string = 'http://tobacco.perceptivemind-eg.com/tobacco-api/api/v1';
  token:any;

  constructor(public http: HttpClient) {
    this.token ="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vdG9iYWNjby5wZXJjZXB0aXZlbWluZC1lZy5jb20vdG9iYWNjby1hcGkvYXBpL3YxL2FjbC91c2Vycy9sb2dpbiIsImlhdCI6MTUwOTYxNDA5MCwiZXhwIjoxNTEyMjQyMDkwLCJuYmYiOjE1MDk2MTQwOTAsImp0aSI6InE3THAxd3VFQUs2b3JuUkciLCJzdWIiOjE1LCJwcnYiOiJiMjNmNzAwYmQ1YmU1YTdjMTNjMmE4NmQ0MGZiYTUwMWZhOWVkNzczIn0.3vIYddLRiP5eyKFdmk-GWIpmY4E2PR7GlQR5s-65TXw";
    //this.header.Authorization ='Bearer '+this.token;
  }
// Custom method to add standard headers.
  public _addStandardHeaders(header:HttpHeaders)
  {
    header = header.append('Content-Type','application/json');
    header = header.append('Accept','application/json');
    header = header.append('Authorization','Bearer '+this.token);
    
    return header;
  }
// custom method to initialize reqOpts
  public _initializeReqOpts(reqOpts)
  {
    if (!reqOpts) {
      reqOpts = {
       headers: new HttpHeaders(),
       params: new HttpParams()
      };
    }
    return reqOpts;
  }
  get(endpoint: string, params?: any, reqOpts?: any) {
    return this.http.get(this.url + '/' + endpoint, reqOpts);
  }

  post(endpoint: string, body: any, reqOpts?: any) {
    return this.http.post(this.url + '/' + endpoint, body, reqOpts);
  }

  put(endpoint: string, body: any, reqOpts?: any) {
    return this.http.put(this.url + '/' + endpoint, body, reqOpts);
  }

  delete(endpoint: string, reqOpts?: any) {
    return this.http.delete(this.url + '/' + endpoint, reqOpts);
  }

  patch(endpoint: string, body: any, reqOpts?: any) {
    return this.http.put(this.url + '/' + endpoint, body, reqOpts);
  }
}

The problem is that my Authorization token is never appended to the headers. When I traced using debugger, I found that reqOpts has my appended headers in something called lazyUpdate. My http call fails as no authorization token was sent so I get an Unauthorized error.
Headers Issue

If anyone could tell me if I am doing something wrong here? How to apply the update.


#2

I have the same problem, did you managed to resolve this?


#3

Have you tried, if it works, when you set the headers like that?

reqOpts = {
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer ' + this.token
  },
  params: new HttpParams()
};

#4

I had a similar issue with .append(),
Using .set worked

new HttpHeaders().set('Authorization','Bearer '+this.token)

.set() should be chained to HttpHeaders()


#5

hi I do have similar problem. I need to add custom headers but the header not working

let headers = new HttpHeaders();
//headers.append(“Content-Type”, ‘application/json; charset=utf-8’);
headers.set(‘id’, ‘105’);
headers.set(‘user_id’, ‘90’);
this.http.get(this.apiUrl, {headers})
.subscribe(
data => {
console.log(data);
},
err => {
console.log("ERROR!: ", err);
}
);

i need to pass id and user_id as custom header and the api will authenticate it. But its not working. I already updated my npm to ionic 3 and latest angular. please help.

thanks


#6
const headers = new HttpHeaders({
  'Content-Type': 'application/json; charset=utf-8',
  id: '105',
  user_id: '90'
});

#7

Sorry but i already do the above but it is still not working:
Here is my code:
let h = new HttpHeaders({
‘Content-Type’: ‘application/json; charset=utf-8’,
merchant_id: ‘105’,
merchant_user_id: ‘90’
});
this.http.get(this.apiUrl, {
headers: h
}).subscribe(
data => {
console.log(data);
//console.log(headers.get(‘merchant_id’));
},
err => {
console.log("ERROR!: ", err);//console.log(headers.get(‘merchant_id’));
}
);

Below is request header: still i wasnt able to send the header.

Accept:/
Accept-Encoding:gzip, deflate
Accept-Language:en-PH,en-US;q=0.9,en;q=0.8
Access-Control-Request-Headers:content-type,merchant_id,merchant_user_id
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
DNT:1
Host:name.com
Origin:http://localhost:8100
Pragma:no-cache
User-Agent:Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30

IONIC INFO:
@ionic/app-scripts : 3.1.8
Cordova Platforms : android 7.0.0
Ionic Framework : ionic-angular 3.9.2

thanks again.


#8

I don’t know headers configuration very well, but does this line say that the headers are set or what does it mean?
Access-Control-Request-Headers:content-type,merchant_id,merchant_user_id

EDIT: Okay I think that access-control-request-headers tell you that these headers are allowed by your server, right?

Are you using the HttpModule with constructor(http: Http) or the HttpClientModule with constructor(http: HttpClient)?

I am using the HttpClient and set the Authorization Header the way described. When i use ionic serve i get the following request header description in chrome dev tools:

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJJbW1vU2NhbiIsInN1YiI6IjVhNmYxNTEwYTcxMmY1MDAxMjE2ODg5MyIsImlhdCI6MTUxNzQxMTIxMzgwNywiZXhwIjoxNTE3NDk3NjEzODA3fQ.N03RXGgErduEQNI2jQDNEpO9h-Mvj3Wv_6kfYae1FBg
Connection:keep-alive
Host:localhost:8100
Referer:http://localhost:8100/
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1

EDIT 2:
This time i tried the following:

...
static createHeadersFromToken(token: string): HttpHeaders {
    return new HttpHeaders({
      Authorization: token,
      merchant_id: '105',
      merchant_user_id: '90'
    });
  }

  constructor(public http: HttpClient) { }
...

and chrome sends this header:

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJJbW1vU2NhbiIsInN1YiI6IjVhNmYxNTEwYTcxMmY1MDAxMjE2ODg5MyIsImlhdCI6MTUxNzQxMTY0MTk2MywiZXhwIjoxNTE3NDk4MDQxOTYzfQ.HfUtkp1LKY1r4EdPKxt5KWvdJYjXmvZ30xJjDcj2PUE
Connection:keep-alive
Host:localhost:8100
If-None-Match:W/"389-c6wWiRCW+lrwlad15id5Dz63lmA"
merchant_id:105
merchant_user_id:90
Referer:http://localhost:8100/
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1

#9

my package dependencies as follows:
"@angular/common": “5.0.3”,
"@angular/compiler": “5.0.3”,
"@angular/compiler-cli": “5.0.3”,
"@angular/core": “5.0.3”,
"@angular/forms": “5.0.3”,
"@angular/http": “5.0.3”,

im new in http. if it is not much can i have a simple complete code wherein you httpclient?

Because i cant still send the header:
filename: app.module.ts

import { BrowserModule } from ‘@angular/platform-browser’;
import { ErrorHandler, NgModule } from ‘@angular/core’;
import { IonicApp, IonicErrorHandler, IonicModule } from ‘ionic-angular’;
import { SplashScreen } from ‘@ionic-native/splash-screen’;
import { StatusBar } from ‘@ionic-native/status-bar’;
import { HttpClientModule } from ‘@angular/common/http’;

import { MyApp } from ‘./app.component’;
import { HomePage } from ‘…/pages/home/home’;

@NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
BrowserModule,
HttpClientModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}

app.component.ts
import { Component } from ‘@angular/core’;
import { Platform } from ‘ionic-angular’;
import { StatusBar } from ‘@ionic-native/status-bar’;
import { SplashScreen } from ‘@ionic-native/splash-screen’;

import { HomePage } from ‘…/pages/home/home’;
import { HttpClient,HttpHeaders } from ‘@angular/common/http’;

@Component({
templateUrl: ‘app.html’
})
export class MyApp {
rootPage:any = HomePage;
apiUrl = “http://domain.com/api/v2/102”; /
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public httpClient:HttpClient) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});

    const h = new HttpHeaders().append('Authorization', 'Basic YXBpOmViYzg3Njg5MjhiZjE1NGIyMTg4NGZlMjU5MDA3NDllMGU0MTRmZGM=');
   //   this.httpClient.get(this.apiUrl, { headers });
  
      this.httpClient.get(this.apiUrl, {headers:h}).subscribe( 
        data => {
          console.log(data);
          //console.log(headers.get('merchant_id'));
        }, 
        err => {
          console.log("ERROR!: ", err);//console.log(headers.get('merchant_id')); 
        }
    );  


  }



  createHeadersFromToken(token: string): HttpHeaders {
    return new HttpHeaders({
      Authorization: token,
      merchant_id: '105',
      merchant_user_id: '90'
    });
}

}


#10
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';

import { HomePage } from '…/pages/home/home';


@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage: any = HomePage;
  apiUrl = 'http://domain.com/api/v2/102';
  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public httpClient: HttpClient) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();
    });

    const headers = new HttpHeaders({
      Authorization: 'Basic YXBpOmViYzg3Njg5MjhiZjE1NGIyMTg4NGZlMjU5MDA3NDllMGU0MTRmZGM=',
      merchant_id: '105',
      merchant_user_id: '90'
    });

    // The response is already mapped to the body, so you have no access to the headers here.
    this.httpClient.get(this.apiUrl, { headers }).subscribe(
      response => {
        console.log('body', response);
      },
      err => {
        console.log('ERROR!: ', err);
      }
    );

    // With observe, you can request the full responseObject. It has the properties body and headers.
    // This time you can read out the headers, but these are from the response from your server, not from your request.
    // To check the headers from your request, you have to use the browser dev tools or read the headers out in your server.
    this.httpClient.get(this.apiUrl, { headers, observe: 'response' }).subscribe(
      response => {
        console.log('body', response.body);
        // This works only if your server responses with the same header.
        console.log('merchant_id', response.headers.get('merchant_id'));
      },
      (err: HttpErrorResponse) => {
        console.log('ERROR!: ', err.message);
        console.log('status', err.status);
      }
    );
  }
}

#11

@densetsughem have you solve this issue? I have the same problem

instead of sending
Authorization:anymous
merchant_id:105
merchant_user_id:90

the request still sending Access-Control-Request-Headers & Access-Control-Request-Method
here what is like

Accept:/
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Access-Control-Request-Headers:authorization,merchant_id,merchant_user_id
Access-Control-Request-Method:GET
Connection:keep-alive
Host:localhost:7070
Origin:http://localhost:8100
User-Agent:Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.168 Mobile Safari/537.36


#12

Hi Nexi,

Thanks for your example code.
I’m using your above example code to try POST method in IONIC. But getting below error.

Access to XMLHttpRequest at ‘http://localhost/ecommerce/public/api/login’ from origin ‘http://localhost:8100’ has been blocked by CORS policy

Could you please help.

image