[BUG] Incorrect Rust code on multiple apiKeys
Created by: nappa85
Bug Report Checklist
-
Have you provided a full/minimal spec to reproduce the issue? -
Have you validated the input using an OpenAPI validator (example)? -
Have you tested with the latest master to confirm the issue still exists? -
Have you searched for related issues/PRs? -
What's the actual output vs expected output? -
[Optional] Sponsorship to speed up the bug fix or feature request (example)
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
- 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