Better way to add HTTP auth headers from SqlStorage?

Hi all, first time using Ionic! I’m trying to wrap my head around the promise/observable patterns and I seem to be coming up short. I’m attempting to create a wrapper for the Angular 2 HTTP object, which basically just adds the proper authorization headers from SqlStorage and sends along the same Observable, which the caller can subscribe to as if it were the original HTTP client, like this:

this.http.get("http://localhost:3000/confirm_auth_token")
    .subscribe(
      data => console.log(data.json())
      //...
    )
)

Here’s what I have so far:

import { Injectable } from '@angular/core';
import { Http, Headers, Response, HTTP_PROVIDERS } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Storage, SqlStorage } from 'ionic-angular';

/*
  A custom wrapper to include headers for API authentication.
  Header info is stored in local storage.
*/

@Injectable()
export class HttpClient {
  headers : Headers;

  constructor(private http: Http) {
  }

  buildHeaders(){
    let headers = new Headers({
      'Accept': 'application/json',
      'Content-Type': 'application/json; charset=utf-8'
    })
    let storage = new Storage(SqlStorage);

    return storage.get("user").then(
      (u) => {
        let user = JSON.parse(u);
        headers.append('X-User-Email', user.email);
        headers.append('X-User-Token', user.authentication_token);
        return headers;
      }
    )
  }

  get(url) {
    return this.buildHeaders().then(
      (headers) => {
        return this.http.get(url, {
          headers: headers
        })
      }
    )
  }
}

However, I’m getting the following error:

Error TS2339: Property 'subscribe' does not exist on type 'Promise<Observable<Response>>'.

So it appears I’m returning the Promise, instead of the Observable this.http.get() request.

Can I somehow “unwrap” the Promise? Is there a better way to do this?

Thank you!

You need to use promise in buildheader function then then will work,
Return new Promise ((resolve, reject) => {…}); sorry im on mobile, cant write whole code :slight_smile:

I had my question answered here:

By replacing my HTTPClient get function with this:

get(url) {
    return Observable
        .fromPromise(this.buildHeaders())
        .switchMap((headers) => this.http.get(url, { headers: headers }));
}

It returns an Observable, so it functions just like the Angular HTTP object. However, I’m still not sure if there is a better way to do auth headers…

2 Likes

Thanks for finding this! This will work for now but I, too, am wondering if there is a better way to do this. It all seems a bit heavy handed for just getting and using a simple key value. I saw an issue on Github where Dan Bucholtz said they are currently refactoring the storage APIs: https://github.com/driftyco/ionic/issues/7446

Maybe something better is on the way.

Thanks alot ! wasted one whole day on this . that worked :slight_smile:

@mikewagz get worked. But , headers are not sent with post method. please help if you could . thank you

I put a similar function for each GET, POST, PUT, DELETE. Here’s what I’m using now - note that now I am returning Promises instead of Observables.

post(url, data) {
  url = this.root + url;
  console.log("POST: ", url)
  return this.buildHeaders()
  .then((headers) => {
    return this.http.post(url, data, { headers: headers })
    .map(res => (<Response>res).json())
    .toPromise()
  })
  .catch(this.handleError.bind(this));
}
1 Like

Thanks ! that worked. :grinning: