Loopback 4 OpenAPI 连接器:为每个请求指定授权 header 值

Loopback 4 OpenAPI connector: Specify Authorization header value per request

我已经按照 here and for unauthorized requests, it is working well; I managed to create the respective datasource, service and controller. My service is similar to the GeocoderProvider example 所述在 Loopback 4 中设置了一个 OpenAPI 连接器,但是,比方说,使用以下服务接口。

export interface MyExternalService {
  search_stuff(params: {query?: string}): Promise<MyExternalServiceResponse>;
}

export interface MyExternalServiceResponse {
  text: string;
}

在我的控制器中,我这样调用它,其中 this.myExternalService 是注入的服务(有点不相关,但 Loopback 也可以隐式解析来自外部 [=28= 的 JSON 响应] 数据源?):

  @get('/search')
  async searchStuff(@param.query.string('query') query: string): Promise<void> {
    return JSON.parse(
      (await this.myExternalService.search_stuff({query})).text,
    );
  }

现在,对应于 myExternalService.search_stuff 的外部端点需要一个 Authorization: Bearer <token> header,其中令牌由客户端 发送到 Loopback ,即它不是一个静态的 API 键左右。假设我将 @param.query.string('token') token: string 添加到我的 searchStuff 控制器方法的参数列表中,我如何将该令牌转发到 OpenAPI 连接器?这是底层 OpenAPI YAML 定义文件的相关部分:

paths:
  /search:
    get:
      security:
        - Authorization: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResults'
      operationId: search-stuff
components:
  securitySchemes:
    Authorization:
      type: http
      scheme: Bearer

我现在使用的是OpenAPI连接器的底层execute函数,手动拦截请求(传给requestInterceptor的对象后来被Swagger直接传给了http模块):

    return JSON.parse(
      (
        await this.myExternalService.execute(
          'search_stuff',
          {query},
          {
            requestInterceptor: (req: {headers: {Authorization: string}}) => {
              req.headers.Authorization = 'Bearer ' + token;
              return req;
            },
          },
        )
      ).text,
    );

我还在MyExternalService接口中添加了如下方法,灵感来自the connector's actual execute function

  execute(
    operationId: string,
    parameters: object,
    options: object,
  ): Promise<MyExternalServiceResponse>;

我发现的一些东西:

  • Loopback 在内部使用 swagger-client 模块来执行基于 OpenAPI 的请求。
  • 特别是 Swagger 的执行函数的 securities 选项需要一个 Security Definitions Object. There are some quirks 并且实际上也将它传递给 Swagger。
  • 在内部,Swagger 构建发送出去的最终 HTTP 请求 here in its source code。在那里,提到了 securities 键,但它从未真正用于请求。这意味着在 this.myExternalService.execute 的第三个参数中手动指定它不会改变任何内容。

我还不会接受这个答案,我期待找到更像环回的方法。

我这样配置我的服务,以注入基本身份验证。

import {inject, lifeCycleObserver, LifeCycleObserver} from '@loopback/core';
import {juggler} from '@loopback/repository';
const SwaggerClient = require('swagger-client');

const config = {
  name: 'jira',
  connector: 'openapi',
  spec: 'swagger-v2.json',
  validate: false,
  httpClient: (request: any) => {
    request.headers["Authorization"] = "Basic " + Buffer.from("test:test").toString('base64');
    return SwaggerClient.http(request);
  },
};

@lifeCycleObserver('datasource')
export class JiraDataSource extends juggler.DataSource
  implements LifeCycleObserver {
  static dataSourceName = 'jira';
  static readonly defaultConfig = config;

  constructor(
    @inject('datasources.config.jira', {optional: true})
    dsConfig: object = config,
  ) {
    super(dsConfig);
  }
}