Angular - 如何将可观察的访问令牌添加到传出的HTTP请求?

问题描述 投票:5回答:2

在我的UserService我有一个用户Observable对象,其中包含用户登录的UserModel。为了测试我在ngOnInit()内部实现了登录过程:

this.userService.authenticate('###', '###')
   .subscribe(res => console.log('authenticated'));
private userSource = new BehaviorSubject<UserModel>(null);
   public user = this.userSource.asObservable();

我的用户模型提供了一个名为authKey的属性,用于API身份验证。

在我的ProjectService中,我想做一个api请求;为了做到这一点,存储在UserModel中的api密钥是必要的。可以只订阅用户属性,但我读到了避免在服务中进行订阅。

如何将此订阅与管道/映射相关联?我的方法是以下代码;但这感觉就像糟糕的代码。

suggest(term: string): Observable<ProjectModel[]> {
      return this.userSrv.user.pipe(
         mergeMap((user: UserModel) => {
            const options = {params: {'access-token': user.accessToken}};

            return this.http.get<ProjectModel[]>(this.conf.url, options).pipe(
               map(response => {
                  // mapping the projects ...
                  return projects;
               })
            );
         })
      );
   }
angular ionic-framework rxjs angular-httpclient
2个回答
1
投票

正如之前的回答中所述,HTTP Interceptor最适合您的用例。

基本想法如下:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
import {mergeMap,map} from 'rxjs/operators';
import {Observable} from 'rxjs';

function isLoginRequest(req: HttpRequest<any>): boolean {
    // implement
}

@Injectable()
export class AccessTokenInterceptor implements HttpInterceptor {
  constructor(private readonly userService: UserService){}

  intercept(req: HttpRequest<any>, next: HttpHandler):
    Observable<HttpEvent<any>> {
    if(isLoginRequest(req)) return next.handle(req);
    return this.userService.user.pipe(
      map(user => req.clone({setParams:{'access-token': user.accessToken}})),
      mergeMap(req => next.handle(req))
    );
  }
}

别忘了注册这个拦截器,如文档中所示。

通过使用此功能,您的原始服务功能将减少为:

suggest(term: string): Observable<ProjectModel[]> {
  return this.http.get<ProjectModel[]>(this.conf.url).pipe(
           map(response => {
              // mapping the projects ...
           })
        );
}

1
投票

您应该使用HttpInterceptor:https://angular.io/api/common/http/HttpInterceptor,而不是传递每个请求的访问令牌。它将为您执行的每个http请求添加AccessToken。将用户存储在UserService中的BehaviorSubject中,并在Interceptor中使用它。

在此之后,您的功能将如下所示:

suggest(term: string): Observable<ProjectModel[]> {
    return this.http.get<ProjectModel[]>(this.conf.url + '/my-endpoint');
}
© www.soinside.com 2019 - 2024. All rights reserved.