OpenAPITools / OpenAPITools/openapi-generator
[BUG] Incorrect Rust code on multiple apiKeys
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Rust generation command and inspect how the generated Configuration and ApiKey types handle security schemes. Reproduce the example with multiple apiKeys and verify the generated client can configure and send each key independently, then cover the corrected behavior with the relevant generator output or test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100