OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.81k stars 6.58k forks source link

[BUG] Incorrect Rust code on multiple apiKeys #8833

Open nappa85 opened 3 years ago

nappa85 commented 3 years ago

Bug Report Checklist

Description

When using multiple apiKeys, Rust generated code insists on the same configuration key for all the apiKeys

openapi-generator version

Tested with: 5.0.1 5.1.0-20210225.082056-71 6.0.0-20210212.130915-8

OpenAPI declaration file content or url
openapi: 3.0.0
servers:
  - url: 'https://api.therocktrading.com/v1'
info:
  description: >-
    TheRockTrading public APIs
  version: 1.0.0
  title: TheRockTrading API
  license:
    name: Apache-2.0
    url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: account
    description: Account API can be seen as user account personal data (balances, ATM withdraw..)
paths:
  /balances:
    get:
      tags:
        - account
      summary: With balances, you will get a list of all your balances in any currency.
      description: ''
      operationId: getBalances
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Balances'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - trt_auth_key: []
          trt_auth_sign: []
          trt_auth_nonce: []
externalDocs:
  description: Find out more about TheRockTrading
  url: 'https://api.therocktrading.com/doc/v1/'
components:
  securitySchemes:
    trt_auth_key:
      type: apiKey
      name: X-TRT-KEY
      in: header
    trt_auth_sign:
      type: apiKey
      name: X-TRT-SIGN
      in: header
    trt_auth_nonce:
      type: apiKey
      name: X-TRT-NONCE
      in: header
  schemas:
    Balance:
      title: Balance
      description: A Currency balance
      type: object
      required:
        - currency
        - balance
        - trading_balance
      properties:
        currency:
          type: string
        balance:
          type: number
          format: double
        trading_balance:
          type: number
          format: double
    Balances:
      title: Balances
      description: A list of currency balances
      type: object
      required:
        - balances
      properties:
        balances:
          type: array
          items:
            $ref: '#/components/schemas/Balance'
    ErrorResponse:
      title: An error response
      description: Describes a single error
      type: object
      required:
        - errors
      properties:
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ErrorMessage'
    ErrorMessage:
      title: An error message
      description: Describes a single error
      type: object
      required:
        - message
      properties:
        message:
          type: string
        code:
          type: string
        meta:
          type: object
          required:
            - key
            - value
          properties:
            key:
              type: string
            value:
              type: string
Generation Details
openapi-generator-cli.sh generate -i openapi.yaml -g rust -o openapi
Steps to reproduce
  1. generate Rust code from an openapi spec that has multiple apiKeys
Related issues/PRs

Haven't found any

Suggest a fix

Instead of using a struct ApiKey, I would use a trait, and implement it for String to make it behave as now.

Actual implementantion:

pub struct Configuration {
    pub base_path: String,
    pub user_agent: Option<String>,
    pub client: reqwest::Client,
    pub basic_auth: Option<BasicAuth>,
    pub oauth_access_token: Option<String>,
    pub bearer_access_token: Option<String>,
    pub api_key: Option<ApiKey>,
    // TODO: take an oauth2 token source, similar to the go one
}

pub struct ApiKey {
    pub prefix: Option<String>,
    pub key: String,
}

My proposal:

pub struct Configuration<A: ApiKey> {
    pub base_path: String,
    pub user_agent: Option<String>,
    pub client: reqwest::Client,
    pub basic_auth: Option<BasicAuth>,
    pub oauth_access_token: Option<String>,
    pub bearer_access_token: Option<String>,
    pub api_key: A,
    // TODO: take an oauth2 token source, similar to the go one
}

pub trait ApiKey {
    fn get_prefix(&self, name: &str) -> Option<String>,
    fn get_key(&self, name: &str) -> Option<String>,
}

impl ApiKey for String {
    fn get_prefix(&self, _: &str) -> Option<String> {
      None
    }
    fn get_key(&self, _: &str) -> Option<String> {
      self.cloned()
    }
}

impl ApiKey for std::collection::HashMap<String, String> {
    fn get_prefix(&self, _: &str) -> Option<String> {
      None
    }
    fn get_key(&self, name: &str) -> Option<String> {
      self.get(name).cloned()
    }
}

/// generated code
    if let Some(ref local_var_apikey) = configuration.api_key {
        if let Some(local_var_key) = local_var_apikey.key.get_key("X-TRT-KEY") {
          let local_var_value = match local_var_apikey.get_prefix("X-TRT-KEY") {
              Some(ref local_var_prefix) => format!("{} {}", local_var_prefix, local_var_key),
              None => local_var_key,
          };
          local_var_req_builder = local_var_req_builder.header("X-TRT-KEY", local_var_value);
      }
    };

This way it's possible to use any type as apiKeys, as long they impl the trait. The same approach can be used for other fields too, if needed

auto-labeler[bot] commented 3 years ago

👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.