salvo-rs / salvo

A powerful web framework built with a simplified design.
https://salvo.rs
Apache License 2.0
3.19k stars 187 forks source link

OAPI : Short FlexNamer doesn't respect schemas name #833

Open rxdiscovery opened 2 months ago

rxdiscovery commented 2 months ago

Hello,

Describe the bug :

I've noticed that when using structures with generics, serialization (ToSchema) doesn't take name changes into account with

#[salvo(schema(name = XXX))]

Here is a complete code that shows the problem :

use salvo::oapi::extract::*;
use salvo::oapi::{endpoint, extract::QueryParam, ToParameters, ToSchema};
use salvo::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, ToSchema)]
#[salvo(schema(name = Response))]
struct Response<T: ToSchema> {
    /// Code response
    code: u32,
    /// Data response
    data: T,
}

#[derive(Serialize, Deserialize, Debug, ToSchema)]
#[salvo(schema(name = Error))]
struct ResponseError {
    /// Code error
    code: String,
    /// error detail
    detail: String,
}

#[derive(Serialize, Deserialize, Debug, ToSchema)]
#[salvo(schema(name = City))]

struct CityDTO {
    /// City id
    id: u64,
    /// City name
    name: String,
}

#[endpoint(
    parameters(("msg",description = "Test param")),
    responses(
    (status_code = 200, description = "success response")
    )
)]
async fn test_generic(
    msg: QueryParam<String, true>,
) -> Result<Json<Response<CityDTO>>, Json<ResponseError>> {
    Ok(Json(Response {
        code: 50,
        data: CityDTO {
            id: 10,
            name: "Beijing".to_string(),
        },
    }))
}

#[endpoint()]
async fn test_primitive() -> Result<Json<Response<String>>, Json<ResponseError>> {
    Ok(Json(Response {
        code: 50,
        data: String::from("cool"),
    }))
}

#[tokio::main]
async fn main() {
    println!("Hello, world!");

    let router = Router::new().push(
        Router::with_path("api")
            .push(Router::with_path("<id>").get(test_generic))
            .push(Router::with_path("cool").get(test_primitive)),
    );

    let doc = OpenApi::new("test api", "0.0.1").merge_router(&router);

    let router = router
        .unshift(doc.into_router("/api-doc/openapi.json"))
        .unshift(
            SwaggerUi::new("/api-doc/openapi.json")
                .title("Test - SwaggerUI")
                .into_router("/swagger-ui"),
        );

    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

We have this result:

Screenshot from 2024-07-15 15-30-59

(for primitive types [String, u32,u64,f32,u64,bool,&str,etc..], it would be nice to display only their names without the path)

Expected result:

Screenshot from 2024-07-15 15-32-09

Salvo version :

salvo = { version = "0.68.5", features = ["oapi", "jwt-auth", "compression"] }
salvo-oapi = "0.68.5"

Thanks in advance :1st_place_medal:

TheAwiteb commented 1 month ago

Use short FlexNamer for now, like this

#[tokio::main]
async fn main() {
    salvo::oapi::naming::set_namer(salvo::oapi::naming::FlexNamer::new().short_mode(true));
    // ...
}

The openAPI will looks like this, it will not respect any name, but is better

image

TheAwiteb commented 1 month ago

@rxdiscovery You can close this issue, or change it to "Short FlexNamerdoesn't respect schemas name", I prefer to change its name

rxdiscovery commented 1 month ago

@TheAwiteb thanks for the temporary solution, I'll try it out.