Nest.JS 和 Observables

Posted

技术标签:

【中文标题】Nest.JS 和 Observables【英文标题】:Nest.JS and Observables 【发布时间】:2022-01-19 01:13:50 【问题描述】:

我是 Nest.JS 的新手,显然不明白如何使用 observables,所以希望你能提供帮助。

基本上我有一个方法需要: 首先:登录到 hashcorp vault 并通过 http 调用返回一个 client_token。 第二:如果我们从保险库中取回了一个令牌,然后我们检查该请求是否包含一个证书 ID,如果没有,我们必须请求生成一个新的证书。这需要来自保险库的 client_token。

我遇到的问题是,当我调用 vault 获取 client_token 时,它没有及时返回,我无法使用它通过第二个 api 调用生成新证书。

我该怎么做才能在下一步中使用 client_token?

这是我最近尝试的代码:

控制器:

@Controller('user')
export class UserController 
  constructor(private readonly userService: UserService) 

  @Post('getUserCert')
  async getUserCert(@Body() loginDto: vaultLoginReqDto) 
    return this.userService.getCertificate(loginDto);
  

Controller 调用 getCertificate 方法:

  getCertificate(loginDto: vaultLoginReqDto) 
    this.loginToVault(loginDto);

    if (this.vault_token) 
      if (loginDto.cert_id) 
        this.checkForExistingCert(loginDto);
       else 
        this.generateNewCert(this.vault_token);
      
     else 
      throw new Error('User is not authorized to access Vault.');
    
  

登录方式:

  loginToVault(loginDto: vaultLoginReqDto) 
    const url = 'http://vault:8200/v1/auth/jwt/login';
    const payload: vaultLoginReqDto = 
      jwt: loginDto.jwt,
      role: loginDto.role,
    ;
    try 
      this.httpService
        .post(url, payload)
        .subscribe((res: AxiosResponse<vaultLoginResDto>) => 
          this.vault_token = res.data.auth.client_token;
        );
     catch (e) 
      this.throwError(e, url, 'Unable to login to vault');
    
  

问题方法是 generateNewCert 方法。它没有及时获得 vault_token。

  generateNewCert(vault_token: string): Observable<string> 
    const url = `http://127.0.0.1:8200/v1/xxxx/xxxx/issue/reader`;
    const payload = 
      common_name: 'id.xxxx.com',
    ;

    const headers = 
      'X-Vault-Token': vault_token,
    ;

    try 
      return this.httpService.post(url, payload,  headers: headers ).pipe(
        map((res: AxiosResponse<vaultGetCertResDto>) => 
          return res.data.data.certificate;
        ),
      );
     catch (e) 
      this.throwError(e, url);
    
  

感谢您的帮助!

【问题讨论】:

【参考方案1】:

使其工作的最简单方法是转换为 Promise,以便您可以等待结果。

loginToVault(loginDto: vaultLoginReqDto) 
  const url = 'http://vault:8200/v1/auth/jwt/login';
  const payload = 
    jwt: loginDto.jwt,
    role: loginDto.role,
  ;

  return this.httpService
    .post(url, payload)
    .pipe(
      catchError(() => /** ...handleError **/),
      map((res) => 
        this.vault_token = res.data.auth.client_token;
        return this.vault_token;
      ),
    )
    .toPromise()

现在,您可以在getCertificate 使用async / await

async getCertificate(loginDto: vaultLoginReqDto) 
  await this.loginToVault(loginDto);
  // or const vault_token = await this.loginToVault(loginDto)

  if (this.vault_token) 
    if (loginDto.cert_id) 
      this.checkForExistingCert(loginDto);
     else 
      this.generateNewCert(this.vault_token);
    
   else 
    throw new Error('User is not authorized to access Vault.');
  

【讨论】:

以上是关于Nest.JS 和 Observables的主要内容,如果未能解决你的问题,请参考以下文章

如何在 typeorm 和 nest.js 中设置布尔验证

带有 sequelize 和 nest.js 的多租户

nest.js + typeORM:基本使用

Nest.js 与 AWS Cognito,如何访问用户属性

MongoDB 和 Nest.js:为集合定义自定义名称

Nest.js 为模型创建静态和实例函数的方法是啥?