Custom response type documentation
imran-mirza79 opened this issue · 2 comments
imran-mirza79 commented
How to override a response with a particular type. I want to return application/cwt
(CBOR web token). I want to return and document application/cwt
type using the TransformOperation for few routes.
y-haidar commented
I would do something like this:
use aide::openapi::{MediaType, SchemaObject};
use axum::{http::StatusCode, response::IntoResponse};
use indexmap::IndexMap;
use schemars::JsonSchema;
use serde::Serialize;
pub struct Cwt<T: Serialize>(pub T);
impl<T: Serialize> IntoResponse for Cwt<T> {
fn into_response(self) -> axum::response::Response {
let mut vec = Vec::new();
// TODO: if `into_writer` is expected to fail then impl error respones
// like `Result<axum::response::Response, CwtRejection>`
// where `CwtRejection` impl IntoResponse
ciborium::into_writer(&self.0, &mut vec).unwrap();
(
StatusCode::OK,
[(axum::http::header::CONTENT_TYPE, "application/cwt")],
vec,
)
.into_response()
}
}
// Taken from: aide-0.13.2/src/axum/outputs.rs
impl<T: JsonSchema + Serialize> aide::OperationOutput for Cwt<T> {
type Inner = T;
fn operation_response(
ctx: &mut aide::gen::GenContext,
_operation: &mut aide::openapi::Operation,
) -> Option<aide::openapi::Response> {
let mut schema = ctx.schema.subschema_for::<T>().into_object();
Some(aide::openapi::Response {
description: schema.metadata().description.clone().unwrap_or_default(),
content: IndexMap::from_iter([(
"application/cwt".into(),
MediaType {
schema: Some(SchemaObject {
json_schema: schema.into(),
example: None,
external_docs: None,
}),
..Default::default()
},
)]),
..Default::default()
})
}
fn inferred_responses(
ctx: &mut aide::gen::GenContext,
operation: &mut aide::openapi::Operation,
) -> Vec<(Option<u16>, aide::openapi::Response)> {
if let Some(res) = Self::operation_response(ctx, operation) {
let success_response = [(Some(200), res)];
Vec::from(success_response)
// if ctx.all_error_responses {
// [
// &success_response,
// // TODO: not implemented
// // CwtRejection::inferred_responses(ctx, operation).as_slice(),
// ]
// .concat()
// } else {
// Vec::from(success_response)
// }
} else {
Vec::new()
}
}
}
// how to use
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct Item {
pub title: Option<String>,
}
/// My endpoint
async fn test_fn() -> Cwt<Item> {
Cwt(Item {
title: Some("Title".to_owned()),
})
}
Please note that I am not familiar with cwt
nor ciborium
crate, check if what I am doing is correct.
imran-mirza79 commented
ooh ok, will try it. Thanks!