Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about getHeaders #57

Closed
JulioWar opened this issue Nov 18, 2016 · 3 comments
Closed

Question about getHeaders #57

JulioWar opened this issue Nov 18, 2016 · 3 comments

Comments

@JulioWar
Copy link

JulioWar commented Nov 18, 2016

Hello.

I'm trying to implement API with OAuth. i made a service to handle that and works propertly but i want to used it in the resources. I created a OAuthGuardResource to extends of it all other Resources

@ResourceParams({
    url: BASE_API,
    add2Provides: false
})
export class OAuthGuardResource extends Resource {

    getHeaders() {
        let headers = super.getHeaders();
        let auth = OAuthService.instance;
        if(auth.hasAuthorization()){
            headers.Authorization = auth.getHeaderAuthorization();
        } else if(auth.hasAuthorizationRefresh()) {
            return auth.refreshToken()
                .toPromise()
                .then(
                    (res: Response) => {
                        auth.saveTokens(res.json());
                        headers.Authorization = auth.getHeaderAuthorization();
                        return headers;
                    }
                ).catch((error: any) => {
                    console.error("Catch OAuthGuardResource Error:",error);
                    return headers;
                });
        } else {
            location.href = BASE+"/login";
        }
        return headers;
    }
}

and i have the UserResource

@ResourceParams({
    url:BASE_API+"/users"
})
export class UserResource extends OAuthGuardResource {
    @ResourceAction({
        isArray: false
    })
    query: ResourceMethod<IUserQueryInput, IUserShort[]>;
}

The thing is when the resource make the query, the method getHeaders is called two times.
I dont know if I'm doing something wrong.

Thanks

@troyanskiy
Copy link
Owner

Hello.
It's strange, it should be called once.
I will check that. Thank you!

@troyanskiy
Copy link
Owner

Hi!
I did some tests with getHeaders and for me it was called once, but it called for every request.
Probably in your case it calls several times refreshToken per page load if you have several api requests and since the token is not valid it will call refreshToken several times. I think you should somehow block other requests and wait until refreshToken will be executed.

Usually i'm implementing AuthGuard resource class which blocks all requests until get config request is not done yet.

import { Request, Response } from '@angular/http';
import { Resource } from 'ng2-resource-rest';
import { Observable, Subscriber } from 'rxjs';
import { AppConfigResource } from './appConfig.resource';
import { IAppConfigEvent, TAppConfigEvent } from '../interfaces/common.interfaces';
import { AuthService, ConfigService } from '../services/index';

export class AuthGuardResource extends Resource {

  private deferredQ: Subscriber<any>[] = [];
  private configListenerSet: boolean = false;

  getHeaders(): any {
    let headers = super.getHeaders();

    headers = AuthService.instance.extendHeaders(headers);

    return headers;
  }

  responseInterceptor(observable: Observable<any>, request?: Request): Observable<any> {

    // Checking is config has been loaded
    if (ConfigService.instance.isLoaded || this instanceof AppConfigResource) {

      return Observable.create((subscriber: Subscriber<any>) => {

        observable.subscribe(
          (res: Response) => {
            if (res.headers) {
              let newToken: string = res.headers.get('X-C3-AUTH-TOKEN');
              if (newToken) {
                AuthService.instance.token = newToken;
              }
            }

            subscriber.next((<any>res)._body ? res.json() : null);
          },
          (error: Response) => {
            if (error.status === 401) {
              AuthService.instance.token = null;
            }
            //console.warn('BaseResource request error', error, request);
            subscriber.error(error);
          },
          () => subscriber.complete()
        );

      });

    }

    // Creating deferred observable
    let retObservable = Observable.create((observer: Subscriber<any>) => {
      this.deferredQ.push(observer);
    }).flatMap(() => this.responseInterceptor(observable));

    this.startConfigListener();

    return retObservable;

  }


  private startConfigListener() {
    if (this.configListenerSet) {
      return;
    }

    this.configListenerSet = true;

    let subscr = ConfigService.instance.eventBus
      .filter((event: IAppConfigEvent) => event.type === TAppConfigEvent.loadSuccess)
      .subscribe(
        () => {
          if (ConfigService.instance.isLoaded) {
            subscr.unsubscribe();
            this.executeDeferred();
          }
        }
      );
  }

  private executeDeferred() {
    let deferredQ = this.deferredQ;
    this.deferredQ = [];
    deferredQ.forEach((deferred) => {
      deferred.next();
      deferred.complete();
    });
  }
}

@JulioWar
Copy link
Author

JulioWar commented Nov 20, 2016

Sorry @troyanskiy, my mistake. 😞
I had not realized that I was doing two queries.
I was looking in the wrong place.

Thanks for your Answare.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants