Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 2 - Get token from Storage value and set Header before HTTP Request

I am using the ionic/storage package to store the api_token for users after they logged in so I can use the unique token to interact with an API.

The problem I am facing is that I need to get the value via storage.get which returns a promise and results in the headers I want to set not being set in time.

I need to return an instance of RequestOptions but can't figure out how to add the header I retrieve when it comes from a promise. Adding a header synchronous with localStorage is working fine when testing so the issue must be the asynch execution.

createAuthorizationHeader(headers: Headers) {
    // this does add the header in time
    localStorage.setItem('api_token', 'some token');
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));

    // this does not add the header in time
    return this.storage.get('api_token').then((value) => {
        headers.append('Authorization', 'Bearer ' + value);
    });
}

getHeaders(path): RequestOptions {
    let headers = new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    });

    if(!this.isGuestRoute(path)) {
        this.createAuthorizationHeader(headers);
    }

    return new RequestOptions({ headers: headers });
}

get(path: string) {
    return this._http.get(this.actionUrl + path, this.getHeaders(path))
        .map(res => res.json())
        .catch(this.handleError);
}

Edit: Working code now looks like this

getApiToken(): Observable<Headers> {
    return Observable.fromPromise(this.storage.get('api_token'));
}

getHeaders(): Headers {
    return new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    });
}

get(path: string) {
    let headers: Headers = this.getHeaders();

    if(!this.isGuestRoute(path)) {
        return this.getApiToken().flatMap(data => {
            headers.append('Authorization', 'Bearer' + data);

            return this._http.get(this.actionUrl + path, { headers : headers })
                .map(res =>  res.json())
                .catch(this.handleError);
        });
    }

    return this._http.get(this.actionUrl + path, { headers : headers })
        .map(res => res.json())
        .catch(this.handleError);
}
like image 719
Chris Mayer Avatar asked May 10 '26 12:05

Chris Mayer


1 Answers

Check out my similar problem Angular2 - Use value of Observable returning method in another Observable

If you convert the Promise to a Observable you will be able to use the rxjs flatMap function.

Let me show you what your would somewhat look like then

getApiToken(): Observable<Headers> {
    return Observable.fromPromise(this.storage.get('api_token'));
   //OR return Observalbe.of(this.storage.get('api_token'));
}

getHeaders(): Headers { 
     //create all headers here except the 'api_token'
     .....
}


get(path: string): Observable<any> {
    let headers: Headers = this.getHeaders();
    return this.getApiToken().flatMap(data => {

       headers.append('Authorization', 'Bearer'+data);

       return this.http.get(this.actionUrl + path, headers)
          .map(res =>  res.json()) 
          .catch(this.handleError);
    });
}

OR (Just learned about this so not sure if it will work)

createAuthorizationHeader(headers: Headers) {
    // this does add the header in time
    localStorage.setItem('api_token', 'some token');
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));

    // this does not add the header in time
    let api_token = await this.storage.get('api_token');
    headers.append('Authorization', 'Bearer ' + api_token);
}
like image 72
Ivar Reukers Avatar answered May 12 '26 12:05

Ivar Reukers



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!