[BUG][RUST-AXUM] rust-axum generator does not handle uuid::Uuid in headerParams
Version used
openapi-generator version: 7.6.0-SNAPSHOT
Description
The rust-axum generator has the following issue:
It is smart enough to detect the format: uuid specifier in openAPI types and map those parameters to the Rust type uuid::Uuid.
Problem: When the openAPI type is within a header, the generated Rust code fails to convert the header value string into a uuid::Uuid because of a missing impl TryFrom<HeaderValue> for IntoHeaderValue<uuid::Uuid> implementation.
This makes generated code like this invalid:
// in src/server/mod.rs
Some(v) => match header::IntoHeaderValue::<uuid::Uuid>::try_from((*v).clone()) {
Specification
This is my minimal openAPI spec that reproduces the issue:
openapi: 3.0.0
info:
title: Sample API
version: 0.1.9
paths:
/users:
post:
summary: Create a user.
description: Adds a user to the users database table.
parameters:
- $ref: "#/components/parameters/CorrelatonIdHeaderParam"
responses:
"201": # status code
description: Added row to table!
content:
application/json:
schema:
type: number
components:
schemas:
CorrelationId:
type: string
format: uuid
example: a9f5a638-728c-479d-af9b-016eb8049ab6
parameters:
CorrelatonIdHeaderParam:
name: some_uid
in: header
required: true
description: lets say we need this.
schema:
$ref: "#/components/schemas/CorrelationId"
Generation details:
I just call the CLI with these options:
java -jar openapi-generator-cli.jar generate -i minimal.yaml -g rust-axum -o out
Suggestion:
A very easy fix would be to add this to the end of the modules/openapi-generator/src/main/resources/rust-axum/header.mustache file unconditionally:
// uuid::Uuid
impl TryFrom<HeaderValue> for IntoHeaderValue<uuid::Uuid> {
type Error = String;
fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
match hdr_value.to_str() {
Ok(hdr_value) => match uuid::Uuid::from_str(hdr_value) {
Ok(uuid) => Ok(IntoHeaderValue(uuid)),
Err(e) => Err(format!("Unable to parse: {} as uuid - {}", hdr_value, e)),
},
Err(e) => Err(format!(
"Unable to convert header {:?} to string {}",
hdr_value, e
)),
}
}
}
impl TryFrom<IntoHeaderValue<uuid::Uuid>> for HeaderValue {
type Error = String;
fn try_from(hdr_value: IntoHeaderValue<uuid::Uuid>) -> Result<Self, Self::Error> {
match HeaderValue::from_bytes(hdr_value.0.as_bytes()) {
Ok(hdr_value) => Ok(hdr_value),
Err(e) => Err(format!(
"Unable to convert {:?} to a header: {}",
hdr_value, e
)),
}
}
}
I wanted to add this code in conditionally, when there is at least one header parameter, with the format set to uuid.
I tried to implement this idea but I neither have any Java experience nor do I understand the flow of the generator program at the moment. What I have tried so far:
Within RustAxumServerCodegen.java in the public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) { function I have collected all the parameters in a list:
private List<String> typesWithinHeader = new ArrayList<>();
// later within public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers)
typesWithinHeader = op.headerParams.stream().map(CodegenParameter::getDataType).collect(Collectors.toList());
Now I would like to add the suggested fix above to headers.mustache only when this array is not empty. In a further step the contents of this array could be used to also add conversion implementations for other types than uuid::Uuid that might break the generated code in the future (I cannot think of any right now).
Also just trying to loop over all header parameters in the header.mustache file does not produce any output at all. I wonder if the template is populated without passing any parameters to it:
{{#headerParams}}
This is not included in the final `header.rs` even though there are `headerParams` in the resulting `CodegenOperation` structure
{{/headerParams}}