In the code below I have posted two examples of what the code is returning in the console. For an interceptor, I'm supposed to be returning an observable. I have converted the local storage promise into an observable using switchmap. I am still getting back null with this method. My observable is wrapped around the function, so I should be getting a value other than null. Thanks!
Interceptor.js
import { fromPromise } from 'rxjs/observable/fromPromise';
accessToken: string;
emptyToken: any;
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
//example
this.storage.get('token').then((val) => {
this.accessToken = val
return console.log(this.accessToken, ' this is returning null value for token')
})
//trying to return actual header
return fromPromise(this.storage.get('token')).switchMap(access => {
this.accessToken = access
console.log(this.accessToken, ' this is returning null value for token')
const authReq = req.clone({
setHeaders: {
Authorization: this.accessToken
}
});
return next.handle(authReq)
})
}
}
I've added the updated the code below, please ignore the code above and still getting the same result. As one of the answers said below, they are correct in all of their assumptions. It's boiled down to getting the token inside of the login observable. The issue is not with the interceptor, that code works fine. I need to somehow get my async value without returning null. The this.storage.ready() method gives me the same result as well. The auth service is being called after my interceptor, so therefore I don't have any token generated yet. How would I go about calling my auth service first?
login(userName: string, password: string, route: string = null): any {
this.storage.set('tokens', 'able to retrieve this token value inside interceptor');
this.logout(false);
this.doLogin(userName, password)
.subscribe(response => {
let token:string = JSON.stringify(response.access_token);
this.storage.set('token', token)
}
}
interceptor.ts
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return Observable.fromPromise(
this.getRequestOptionArgs(options)
).mergeMap((options) => {
return super.get(url, options)
})
}
private getRequestOptionArgs(options?: RequestOptionsArgs) {
return this.storage.get('token').then((token) => {
console.log(token, 'token for the get')
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
if (token !== null) {
options.headers.append('Authorization', 'Bearer ' + token);
}
options.headers.append('Content-Type', 'application/json');
return options;
});
}
I think the problem is that your StorageService
is returning null
, rather than this being a problem with the Interceptor.
The storage service is using a Promise, meaning it will only emit one value. If you are getting null
then I guess you don't yet have the token in storage.
Where do you get the token from in the first place? The server? In which case this first request won't have the token.
But... you've said that when you access localStorage
directly (synchronously) then you get a value and it all works. So I'm assuming you already have a token in storage.
Looking at the docs for Ionic Storage it looks like there is another possibility. The storage has a ready
method, so perhaps the store isn't ready.
You could try something like this (untested) where you first wait for the ready promise to resolve before trying to get the token:
import { Injectable } from '@angular/core';
import { HttpErrorResponse, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/observable/fromPromise';
@Injectable()
export class Interceptor implements HttpInterceptor {
constructor (private storage: StorageService) {}
intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// chain the ready promise with the get token promise
return Observable.fromPromise(this.storage.ready().then(this.storage.get('token')))
.mergeMap((token: string) => {
const authReq = request.clone({
setHeaders: {
Authorization: token
}
});
return next.handle(authReq);
});
}
}
Just a guess...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With