[Rust-Axum][Breaking Change] Implement a customizable error handler (#20463)

* Implement a custom error handler for unhandled or generic endpoint errors

* Pass in method, host and cookies to error handler

* Update axum to 0.8

* Make API methods take references instead of ownership

* Multipart is also part of the axum update

* Prevent replacing path names with the same name as a dynamic path parameter

* Use status code name instead of number

* Rollback axum update

* Forgot paths
This commit is contained in:
Victoria Casasampere Fernandez 2025-02-09 14:54:01 +01:00 committed by GitHub
parent ba0456aa91
commit adbbe68d4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
81 changed files with 2695 additions and 1649 deletions

View File

@ -62,7 +62,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -48,16 +48,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl {{{packageName}}}::Api for ServerImpl {
impl {{{externCrateName}}}::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl {{{externCrateName}}}::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = {{{packageName}}}::server::new(Arc::new(ServerImpl));
let app = {{{externCrateName}}}::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -28,3 +28,23 @@ pub trait ApiKeyAuthHeader {
{{/isKeyInHeader}}
{{/isApiKey}}
{{/authMethods}}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -17,7 +17,7 @@ use crate::{models, types::*};
/// {{classnamePascalCase}}
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait {{classnamePascalCase}} {
pub trait {{classnamePascalCase}}<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
{{#havingAuthMethod}}
type Claims;
@ -31,36 +31,36 @@ pub trait {{classnamePascalCase}} {
/// {{{operationId}}} - {{{httpMethod}}} {{{basePathWithoutHost}}}{{{path}}}
async fn {{{x-operation-id}}}(
&self,
method: Method,
host: Host,
cookies: CookieJar,
method: &Method,
host: &Host,
cookies: &CookieJar,
{{#vendorExtensions}}
{{#x-has-auth-methods}}
claims: Self::Claims,
claims: &Self::Claims,
{{/x-has-auth-methods}}
{{/vendorExtensions}}
{{#headerParams.size}}
header_params: models::{{{operationIdCamelCase}}}HeaderParams,
header_params: &models::{{{operationIdCamelCase}}}HeaderParams,
{{/headerParams.size}}
{{#pathParams.size}}
path_params: models::{{{operationIdCamelCase}}}PathParams,
path_params: &models::{{{operationIdCamelCase}}}PathParams,
{{/pathParams.size}}
{{#queryParams.size}}
query_params: models::{{{operationIdCamelCase}}}QueryParams,
query_params: &models::{{{operationIdCamelCase}}}QueryParams,
{{/queryParams.size}}
{{^x-consumes-multipart-related}}
{{^x-consumes-multipart}}
{{#bodyParam}}
{{#vendorExtensions}}
{{^x-consumes-plain-text}}
body: {{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}},
body: &{{^required}}Option<{{/required}}{{{dataType}}}{{^required}}>{{/required}},
{{/x-consumes-plain-text}}
{{#x-consumes-plain-text}}
{{#isString}}
body: String,
body: &String,
{{/isString}}
{{^isString}}
body: Bytes,
body: &Bytes,
{{/isString}}
{{/x-consumes-plain-text}}
{{/vendorExtensions}}
@ -68,12 +68,12 @@ pub trait {{classnamePascalCase}} {
{{/x-consumes-multipart}}
{{/x-consumes-multipart-related}}
{{#x-consumes-multipart}}
body: Multipart,
body: &Multipart,
{{/x-consumes-multipart}}
{{#x-consumes-multipart-related}}
body: axum::body::Body,
body: &axum::body::Body,
{{/x-consumes-multipart-related}}
) -> Result<{{{operationId}}}Response, ()>;
) -> Result<{{{operationId}}}Response, E>;
{{/vendorExtensions}}
{{^-last}}

View File

@ -1,6 +1,6 @@
/// {{{operationId}}} - {{{httpMethod}}} {{{basePathWithoutHost}}}{{{path}}}
#[tracing::instrument(skip_all)]
async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A{{#havingAuthMethod}}, C{{/havingAuthMethod}}>(
async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A, E{{#havingAuthMethod}}, C{{/havingAuthMethod}}>(
method: Method,
host: Host,
cookies: CookieJar,
@ -54,8 +54,9 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A{{#h
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::{{classFilename}}::{{classnamePascalCase}}{{#havingAuthMethod}}<Claims = C>{{/havingAuthMethod}}{{#vendorExtensions}}{{#x-has-cookie-auth-methods}}+ apis::CookieAuthentication<Claims = C>{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}+ apis::ApiKeyAuthHeader<Claims = C>{{/x-has-header-auth-methods}}{{/vendorExtensions}},
{
A: apis::{{classFilename}}::{{classnamePascalCase}}<E{{#havingAuthMethod}}, Claims = C{{/havingAuthMethod}}>{{#vendorExtensions}}{{#x-has-cookie-auth-methods}}+ apis::CookieAuthentication<Claims = C>{{/x-has-cookie-auth-methods}}{{#x-has-header-auth-methods}}+ apis::ApiKeyAuthHeader<Claims = C>{{/x-has-header-auth-methods}}{{/vendorExtensions}} + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
{{#vendorExtensions}}
{{#x-has-auth-methods}}
// Authentication
@ -186,38 +187,38 @@ where
{{/disableValidator}}
let result = api_impl.as_ref().{{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}(
method,
host,
cookies,
&method,
&host,
&cookies,
{{#vendorExtensions}}
{{#x-has-auth-methods}}
claims,
&claims,
{{/x-has-auth-methods}}
{{/vendorExtensions}}
{{#headerParams.size}}
header_params,
&header_params,
{{/headerParams.size}}
{{#pathParams.size}}
path_params,
&path_params,
{{/pathParams.size}}
{{#queryParams.size}}
query_params,
&query_params,
{{/queryParams.size}}
{{#vendorExtensions}}
{{^x-consumes-multipart-related}}
{{^x-consumes-multipart}}
{{#bodyParams}}
{{#-first}}
body,
&body,
{{/-first}}
{{/bodyParams}}
{{/x-consumes-multipart}}
{{/x-consumes-multipart-related}}
{{#x-consumes-multipart}}
body,
&body,
{{/x-consumes-multipart}}
{{#x-consumes-multipart-related}}
body,
&body,
{{/x-consumes-multipart-related}}
{{/vendorExtensions}}
).await;
@ -342,10 +343,11 @@ where
},
{{/responses}}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
},
};

View File

@ -1,15 +1,16 @@
/// Setup API Server.
pub fn new<I, A{{#havingAuthMethods}}, C{{/havingAuthMethods}}>(api_impl: I) -> Router
pub fn new<I, A, E{{#havingAuthMethods}}, C{{/havingAuthMethods}}>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}}{{#havingAuthMethod}}<Claims = C>{{/havingAuthMethod}} + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication<Claims = C> + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader<Claims = C> + {{/isKeyInHeader}}{{/isApiKey}}{{/authMethods}}'static,
A: {{#apiInfo}}{{#apis}}{{#operations}}apis::{{classFilename}}::{{classnamePascalCase}}<E{{#havingAuthMethod}}, Claims = C{{/havingAuthMethod}}> + {{/operations}}{{/apis}}{{/apiInfo}}{{#authMethods}}{{#isApiKey}}{{#isKeyInCookie}}apis::CookieAuthentication<Claims = C> + {{/isKeyInCookie}}{{#isKeyInHeader}}apis::ApiKeyAuthHeader<Claims = C> + {{/isKeyInHeader}}{{/isApiKey}}{{/authMethods}}Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{{#havingAuthMethods}}C: Send + Sync + 'static,{{/havingAuthMethods}}
{
// build our application with a route
Router::new()
{{#pathMethodOps}}
.route("{{{basePathWithoutHost}}}{{{path}}}",
{{#methodOperations}}{{{method}}}({{{operationID}}}::<I, A{{#vendorExtensions}}{{#havingAuthMethod}}, C{{/havingAuthMethod}}{{/vendorExtensions}}>){{^-last}}.{{/-last}}{{/methodOperations}}
{{#methodOperations}}{{{method}}}({{{operationID}}}::<I, A, E{{#vendorExtensions}}{{#havingAuthMethod}}, C{{/havingAuthMethod}}{{/vendorExtensions}}>){{^-last}}.{{/-last}}{{/methodOperations}}
)
{{/pathMethodOps}}
.with_state(api_impl)

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 1.0.0
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl apikey-auths::Api for ServerImpl {
impl apikey_auths::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl apikey_auths::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = apikey-auths::server::new(Arc::new(ServerImpl));
let app = apikey_auths::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -24,3 +24,23 @@ pub trait CookieAuthentication {
key: &str,
) -> Option<Self::Claims>;
}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -38,7 +38,9 @@ pub enum PostMakePaymentResponse {
/// Payments
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Payments {
pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
super::ErrorHandler<E>
{
type Claims;
/// Get payment method by id.
@ -46,31 +48,31 @@ pub trait Payments {
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
async fn get_payment_method_by_id(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::GetPaymentMethodByIdPathParams,
) -> Result<GetPaymentMethodByIdResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::GetPaymentMethodByIdPathParams,
) -> Result<GetPaymentMethodByIdResponse, E>;
/// Get payment methods.
///
/// GetPaymentMethods - GET /v71/paymentMethods
async fn get_payment_methods(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<GetPaymentMethodsResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<GetPaymentMethodsResponse, E>;
/// Make a payment.
///
/// PostMakePayment - POST /v71/payments
async fn post_make_payment(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
body: Option<models::Payment>,
) -> Result<PostMakePaymentResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
body: &Option<models::Payment>,
) -> Result<PostMakePaymentResponse, E>;
}

View File

@ -13,23 +13,29 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A, C>(api_impl: I) -> Router
pub fn new<I, A, E, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::payments::Payments<Claims = C>
A: apis::payments::Payments<E, Claims = C>
+ apis::ApiKeyAuthHeader<Claims = C>
+ apis::CookieAuthentication<Claims = C>
+ Send
+ Sync
+ 'static,
E: std::fmt::Debug + Send + Sync + 'static,
C: Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/v71/paymentMethods", get(get_payment_methods::<I, A, C>))
.route(
"/v71/paymentMethods",
get(get_payment_methods::<I, A, E, C>),
)
.route(
"/v71/paymentMethods/:id",
get(get_payment_method_by_id::<I, A, C>),
get(get_payment_method_by_id::<I, A, E, C>),
)
.route("/v71/payments", post(post_make_payment::<I, A, C>))
.route("/v71/payments", post(post_make_payment::<I, A, E, C>))
.with_state(api_impl)
}
@ -43,7 +49,7 @@ fn get_payment_method_by_id_validation(
}
/// GetPaymentMethodById - GET /v71/paymentMethods/{id}
#[tracing::instrument(skip_all)]
async fn get_payment_method_by_id<I, A, C>(
async fn get_payment_method_by_id<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -52,7 +58,8 @@ async fn get_payment_method_by_id<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments<Claims = C>,
A: apis::payments::Payments<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -69,7 +76,7 @@ where
let result = api_impl
.as_ref()
.get_payment_method_by_id(method, host, cookies, path_params)
.get_payment_method_by_id(&method, &host, &cookies, &path_params)
.await;
let mut response = Response::builder();
@ -123,10 +130,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -142,7 +153,7 @@ fn get_payment_methods_validation() -> std::result::Result<(), ValidationErrors>
}
/// GetPaymentMethods - GET /v71/paymentMethods
#[tracing::instrument(skip_all)]
async fn get_payment_methods<I, A, C>(
async fn get_payment_methods<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -150,7 +161,8 @@ async fn get_payment_methods<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments<Claims = C>,
A: apis::payments::Payments<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_payment_methods_validation())
@ -166,7 +178,7 @@ where
let result = api_impl
.as_ref()
.get_payment_methods(method, host, cookies)
.get_payment_methods(&method, &host, &cookies)
.await;
let mut response = Response::builder();
@ -197,10 +209,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -230,7 +246,7 @@ fn post_make_payment_validation(
}
/// PostMakePayment - POST /v71/payments
#[tracing::instrument(skip_all)]
async fn post_make_payment<I, A, C>(
async fn post_make_payment<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -239,7 +255,11 @@ async fn post_make_payment<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments<Claims = C> + apis::CookieAuthentication<Claims = C>,
A: apis::payments::Payments<E, Claims = C>
+ apis::CookieAuthentication<Claims = C>
+ Send
+ Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_cookie = api_impl
@ -268,7 +288,7 @@ where
let result = api_impl
.as_ref()
.post_make_payment(method, host, cookies, claims, body)
.post_make_payment(&method, &host, &cookies, &claims, &body)
.await;
let mut response = Response::builder();
@ -322,10 +342,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 1.0.7
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl multipart-v3::Api for ServerImpl {
impl multipart_v3::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl multipart_v3::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = multipart-v3::server::new(Arc::new(ServerImpl));
let app = multipart_v3::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -34,31 +34,31 @@ pub enum MultipleIdenticalMimeTypesPostResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// MultipartRelatedRequestPost - POST /multipart_related_request
async fn multipart_related_request_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: axum::body::Body,
) -> Result<MultipartRelatedRequestPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &axum::body::Body,
) -> Result<MultipartRelatedRequestPostResponse, E>;
/// MultipartRequestPost - POST /multipart_request
async fn multipart_request_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Multipart,
) -> Result<MultipartRequestPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Multipart,
) -> Result<MultipartRequestPostResponse, E>;
/// MultipleIdenticalMimeTypesPost - POST /multiple-identical-mime-types
async fn multiple_identical_mime_types_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: axum::body::Body,
) -> Result<MultipleIdenticalMimeTypesPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &axum::body::Body,
) -> Result<MultipleIdenticalMimeTypesPostResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -13,21 +13,25 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, E>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::default::Default + 'static,
A: apis::default::Default<E> + Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route(
"/multipart_related_request",
post(multipart_related_request_post::<I, A>),
post(multipart_related_request_post::<I, A, E>),
)
.route(
"/multipart_request",
post(multipart_request_post::<I, A, E>),
)
.route("/multipart_request", post(multipart_request_post::<I, A>))
.route(
"/multiple-identical-mime-types",
post(multiple_identical_mime_types_post::<I, A>),
post(multiple_identical_mime_types_post::<I, A, E>),
)
.with_state(api_impl)
}
@ -38,7 +42,7 @@ fn multipart_related_request_post_validation() -> std::result::Result<(), Valida
}
/// MultipartRelatedRequestPost - POST /multipart_related_request
#[tracing::instrument(skip_all)]
async fn multipart_related_request_post<I, A>(
async fn multipart_related_request_post<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -47,7 +51,8 @@ async fn multipart_related_request_post<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -64,7 +69,7 @@ where
let result = api_impl
.as_ref()
.multipart_related_request_post(method, host, cookies, body)
.multipart_related_request_post(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -76,10 +81,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -95,7 +104,7 @@ fn multipart_request_post_validation() -> std::result::Result<(), ValidationErro
}
/// MultipartRequestPost - POST /multipart_request
#[tracing::instrument(skip_all)]
async fn multipart_request_post<I, A>(
async fn multipart_request_post<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -104,7 +113,8 @@ async fn multipart_request_post<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || multipart_request_post_validation())
@ -120,7 +130,7 @@ where
let result = api_impl
.as_ref()
.multipart_request_post(method, host, cookies, body)
.multipart_request_post(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -132,10 +142,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -151,7 +165,7 @@ fn multiple_identical_mime_types_post_validation() -> std::result::Result<(), Va
}
/// MultipleIdenticalMimeTypesPost - POST /multiple-identical-mime-types
#[tracing::instrument(skip_all)]
async fn multiple_identical_mime_types_post<I, A>(
async fn multiple_identical_mime_types_post<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -160,7 +174,8 @@ async fn multiple_identical_mime_types_post<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -177,7 +192,7 @@ where
let result = api_impl
.as_ref()
.multiple_identical_mime_types_post(method, host, cookies, body)
.multiple_identical_mime_types_post(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -189,10 +204,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 1.0.7
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl openapi-v3::Api for ServerImpl {
impl openapi_v3::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl openapi_v3::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = openapi-v3::server::new(Arc::new(ServerImpl));
let app = openapi_v3::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -274,255 +274,255 @@ pub enum XmlPutResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// AnyOfGet - GET /any-of
async fn any_of_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::AnyOfGetQueryParams,
) -> Result<AnyOfGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::AnyOfGetQueryParams,
) -> Result<AnyOfGetResponse, E>;
/// CallbackWithHeaderPost - POST /callback-with-header
async fn callback_with_header_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::CallbackWithHeaderPostQueryParams,
) -> Result<CallbackWithHeaderPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::CallbackWithHeaderPostQueryParams,
) -> Result<CallbackWithHeaderPostResponse, E>;
/// ComplexQueryParamGet - GET /complex-query-param
async fn complex_query_param_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::ComplexQueryParamGetQueryParams,
) -> Result<ComplexQueryParamGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::ComplexQueryParamGetQueryParams,
) -> Result<ComplexQueryParamGetResponse, E>;
/// EnumInPathPathParamGet - GET /enum_in_path/{path_param}
async fn enum_in_path_path_param_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::EnumInPathPathParamGetPathParams,
) -> Result<EnumInPathPathParamGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::EnumInPathPathParamGetPathParams,
) -> Result<EnumInPathPathParamGetResponse, E>;
/// Test a Form Post.
///
/// FormTest - POST /form-test
async fn form_test(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::FormTestRequest,
) -> Result<FormTestResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::FormTestRequest,
) -> Result<FormTestResponse, E>;
/// GetWithBooleanParameter - GET /get-with-bool
async fn get_with_boolean_parameter(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::GetWithBooleanParameterQueryParams,
) -> Result<GetWithBooleanParameterResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::GetWithBooleanParameterQueryParams,
) -> Result<GetWithBooleanParameterResponse, E>;
/// JsonComplexQueryParamGet - GET /json-complex-query-param
async fn json_complex_query_param_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::JsonComplexQueryParamGetQueryParams,
) -> Result<JsonComplexQueryParamGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::JsonComplexQueryParamGetQueryParams,
) -> Result<JsonComplexQueryParamGetResponse, E>;
/// MandatoryRequestHeaderGet - GET /mandatory-request-header
async fn mandatory_request_header_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
header_params: models::MandatoryRequestHeaderGetHeaderParams,
) -> Result<MandatoryRequestHeaderGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
header_params: &models::MandatoryRequestHeaderGetHeaderParams,
) -> Result<MandatoryRequestHeaderGetResponse, E>;
/// MergePatchJsonGet - GET /merge-patch-json
async fn merge_patch_json_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<MergePatchJsonGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<MergePatchJsonGetResponse, E>;
/// Get some stuff..
///
/// MultigetGet - GET /multiget
async fn multiget_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<MultigetGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<MultigetGetResponse, E>;
/// MultipleAuthSchemeGet - GET /multiple_auth_scheme
async fn multiple_auth_scheme_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<MultipleAuthSchemeGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<MultipleAuthSchemeGetResponse, E>;
/// MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet - GET /multiple-path-params-with-very-long-path-to-test-formatting/{path_param_a}/{path_param_b}
async fn multiple_path_params_with_very_long_path_to_test_formatting_path_param_a_path_param_b_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGetPathParams,
) -> Result<MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGetPathParams,
) -> Result<MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGetResponse, E>;
/// OneOfGet - GET /one-of
async fn one_of_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<OneOfGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<OneOfGetResponse, E>;
/// OverrideServerGet - GET /override-server
async fn override_server_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<OverrideServerGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<OverrideServerGetResponse, E>;
/// Get some stuff with parameters..
///
/// ParamgetGet - GET /paramget
async fn paramget_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::ParamgetGetQueryParams,
) -> Result<ParamgetGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::ParamgetGetQueryParams,
) -> Result<ParamgetGetResponse, E>;
/// ReadonlyAuthSchemeGet - GET /readonly_auth_scheme
async fn readonly_auth_scheme_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<ReadonlyAuthSchemeGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<ReadonlyAuthSchemeGetResponse, E>;
/// RegisterCallbackPost - POST /register-callback
async fn register_callback_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::RegisterCallbackPostQueryParams,
) -> Result<RegisterCallbackPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::RegisterCallbackPostQueryParams,
) -> Result<RegisterCallbackPostResponse, E>;
/// RequiredOctetStreamPut - PUT /required_octet_stream
async fn required_octet_stream_put(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Bytes,
) -> Result<RequiredOctetStreamPutResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Bytes,
) -> Result<RequiredOctetStreamPutResponse, E>;
/// ResponsesWithHeadersGet - GET /responses_with_headers
async fn responses_with_headers_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<ResponsesWithHeadersGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<ResponsesWithHeadersGetResponse, E>;
/// Rfc7807Get - GET /rfc7807
async fn rfc7807_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Rfc7807GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Rfc7807GetResponse, E>;
/// TwoFirstLetterHeaders - POST /operation-two-first-letter-headers
async fn two_first_letter_headers(
&self,
method: Method,
host: Host,
cookies: CookieJar,
header_params: models::TwoFirstLetterHeadersHeaderParams,
) -> Result<TwoFirstLetterHeadersResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
header_params: &models::TwoFirstLetterHeadersHeaderParams,
) -> Result<TwoFirstLetterHeadersResponse, E>;
/// UntypedPropertyGet - GET /untyped_property
async fn untyped_property_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Option<models::ObjectUntypedProps>,
) -> Result<UntypedPropertyGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Option<models::ObjectUntypedProps>,
) -> Result<UntypedPropertyGetResponse, E>;
/// UuidGet - GET /uuid
async fn uuid_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<UuidGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<UuidGetResponse, E>;
/// XmlExtraPost - POST /xml_extra
async fn xml_extra_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Bytes,
) -> Result<XmlExtraPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Bytes,
) -> Result<XmlExtraPostResponse, E>;
/// XmlOtherPost - POST /xml_other
async fn xml_other_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Bytes,
) -> Result<XmlOtherPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Bytes,
) -> Result<XmlOtherPostResponse, E>;
/// XmlOtherPut - PUT /xml_other
async fn xml_other_put(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Bytes,
) -> Result<XmlOtherPutResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Bytes,
) -> Result<XmlOtherPutResponse, E>;
/// Post an array. It's important we test apostrophes, so include one here..
///
/// XmlPost - POST /xml
async fn xml_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Bytes,
) -> Result<XmlPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Bytes,
) -> Result<XmlPostResponse, E>;
/// XmlPut - PUT /xml
async fn xml_put(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Bytes,
) -> Result<XmlPutResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Bytes,
) -> Result<XmlPutResponse, E>;
}

View File

@ -18,13 +18,15 @@ pub enum GetRepoInfoResponse {
/// InfoRepo
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait InfoRepo {
pub trait InfoRepo<E: std::fmt::Debug + Send + Sync + 'static = ()>:
super::ErrorHandler<E>
{
/// GetRepoInfo - GET /repos/{repoId}
async fn get_repo_info(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::GetRepoInfoPathParams,
) -> Result<GetRepoInfoResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::GetRepoInfoPathParams,
) -> Result<GetRepoInfoResponse, E>;
}

View File

@ -1,3 +1,23 @@
pub mod default;
pub mod info_repo;
pub mod repo;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -18,13 +18,13 @@ pub enum CreateRepoResponse {
/// Repo
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Repo {
pub trait Repo<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// CreateRepo - POST /repos
async fn create_repo(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::ObjectParam,
) -> Result<CreateRepoResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::ObjectParam,
) -> Result<CreateRepoResponse, E>;
}

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 0.0.1
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl ops-v3::Api for ServerImpl {
impl ops_v3::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl ops_v3::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = ops-v3::server::new(Arc::new(ServerImpl));
let app = ops_v3::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -306,300 +306,300 @@ pub enum Op9GetResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// Op10Get - GET /op10
async fn op10_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op10GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op10GetResponse, E>;
/// Op11Get - GET /op11
async fn op11_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op11GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op11GetResponse, E>;
/// Op12Get - GET /op12
async fn op12_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op12GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op12GetResponse, E>;
/// Op13Get - GET /op13
async fn op13_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op13GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op13GetResponse, E>;
/// Op14Get - GET /op14
async fn op14_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op14GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op14GetResponse, E>;
/// Op15Get - GET /op15
async fn op15_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op15GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op15GetResponse, E>;
/// Op16Get - GET /op16
async fn op16_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op16GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op16GetResponse, E>;
/// Op17Get - GET /op17
async fn op17_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op17GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op17GetResponse, E>;
/// Op18Get - GET /op18
async fn op18_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op18GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op18GetResponse, E>;
/// Op19Get - GET /op19
async fn op19_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op19GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op19GetResponse, E>;
/// Op1Get - GET /op1
async fn op1_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op1GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op1GetResponse, E>;
/// Op20Get - GET /op20
async fn op20_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op20GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op20GetResponse, E>;
/// Op21Get - GET /op21
async fn op21_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op21GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op21GetResponse, E>;
/// Op22Get - GET /op22
async fn op22_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op22GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op22GetResponse, E>;
/// Op23Get - GET /op23
async fn op23_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op23GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op23GetResponse, E>;
/// Op24Get - GET /op24
async fn op24_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op24GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op24GetResponse, E>;
/// Op25Get - GET /op25
async fn op25_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op25GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op25GetResponse, E>;
/// Op26Get - GET /op26
async fn op26_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op26GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op26GetResponse, E>;
/// Op27Get - GET /op27
async fn op27_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op27GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op27GetResponse, E>;
/// Op28Get - GET /op28
async fn op28_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op28GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op28GetResponse, E>;
/// Op29Get - GET /op29
async fn op29_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op29GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op29GetResponse, E>;
/// Op2Get - GET /op2
async fn op2_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op2GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op2GetResponse, E>;
/// Op30Get - GET /op30
async fn op30_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op30GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op30GetResponse, E>;
/// Op31Get - GET /op31
async fn op31_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op31GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op31GetResponse, E>;
/// Op32Get - GET /op32
async fn op32_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op32GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op32GetResponse, E>;
/// Op33Get - GET /op33
async fn op33_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op33GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op33GetResponse, E>;
/// Op34Get - GET /op34
async fn op34_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op34GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op34GetResponse, E>;
/// Op35Get - GET /op35
async fn op35_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op35GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op35GetResponse, E>;
/// Op36Get - GET /op36
async fn op36_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op36GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op36GetResponse, E>;
/// Op37Get - GET /op37
async fn op37_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op37GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op37GetResponse, E>;
/// Op3Get - GET /op3
async fn op3_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op3GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op3GetResponse, E>;
/// Op4Get - GET /op4
async fn op4_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op4GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op4GetResponse, E>;
/// Op5Get - GET /op5
async fn op5_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op5GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op5GetResponse, E>;
/// Op6Get - GET /op6
async fn op6_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op6GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op6GetResponse, E>;
/// Op7Get - GET /op7
async fn op7_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op7GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op7GetResponse, E>;
/// Op8Get - GET /op8
async fn op8_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op8GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op8GetResponse, E>;
/// Op9Get - GET /op9
async fn op9_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Op9GetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Op9GetResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -42,7 +42,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 1.0.0
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl petstore-with-fake-endpoints-models-for-testing::Api for ServerImpl {
impl petstore_with_fake_endpoints_models_for_testing::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl petstore_with_fake_endpoints_models_for_testing::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = petstore-with-fake-endpoints-models-for-testing::server::new(Arc::new(ServerImpl));
let app = petstore_with_fake_endpoints_models_for_testing::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -18,15 +18,17 @@ pub enum TestSpecialTagsResponse {
/// AnotherFake
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait AnotherFake {
pub trait AnotherFake<E: std::fmt::Debug + Send + Sync + 'static = ()>:
super::ErrorHandler<E>
{
/// To test special tags.
///
/// TestSpecialTags - PATCH /v2/another-fake/dummy
async fn test_special_tags(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Client,
) -> Result<TestSpecialTagsResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Client,
) -> Result<TestSpecialTagsResponse, E>;
}

View File

@ -118,132 +118,132 @@ pub enum TestJsonFormDataResponse {
/// Fake
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Fake {
pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// Call123example - GET /v2/fake/operation-with-numeric-id
async fn call123example(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<Call123exampleResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<Call123exampleResponse, E>;
/// FakeOuterBooleanSerialize - POST /v2/fake/outer/boolean
async fn fake_outer_boolean_serialize(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Option<models::OuterBoolean>,
) -> Result<FakeOuterBooleanSerializeResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Option<models::OuterBoolean>,
) -> Result<FakeOuterBooleanSerializeResponse, E>;
/// FakeOuterCompositeSerialize - POST /v2/fake/outer/composite
async fn fake_outer_composite_serialize(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Option<models::OuterComposite>,
) -> Result<FakeOuterCompositeSerializeResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Option<models::OuterComposite>,
) -> Result<FakeOuterCompositeSerializeResponse, E>;
/// FakeOuterNumberSerialize - POST /v2/fake/outer/number
async fn fake_outer_number_serialize(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Option<models::OuterNumber>,
) -> Result<FakeOuterNumberSerializeResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Option<models::OuterNumber>,
) -> Result<FakeOuterNumberSerializeResponse, E>;
/// FakeOuterStringSerialize - POST /v2/fake/outer/string
async fn fake_outer_string_serialize(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Option<models::OuterString>,
) -> Result<FakeOuterStringSerializeResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Option<models::OuterString>,
) -> Result<FakeOuterStringSerializeResponse, E>;
/// FakeResponseWithNumericalDescription - GET /v2/fake/response-with-numerical-description
async fn fake_response_with_numerical_description(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<FakeResponseWithNumericalDescriptionResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<FakeResponseWithNumericalDescriptionResponse, E>;
/// HyphenParam - GET /v2/fake/hyphenParam/{hyphen-param}
async fn hyphen_param(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::HyphenParamPathParams,
) -> Result<HyphenParamResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::HyphenParamPathParams,
) -> Result<HyphenParamResponse, E>;
/// TestBodyWithQueryParams - PUT /v2/fake/body-with-query-params
async fn test_body_with_query_params(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::TestBodyWithQueryParamsQueryParams,
body: models::User,
) -> Result<TestBodyWithQueryParamsResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::TestBodyWithQueryParamsQueryParams,
body: &models::User,
) -> Result<TestBodyWithQueryParamsResponse, E>;
/// To test \"client\" model.
///
/// TestClientModel - PATCH /v2/fake
async fn test_client_model(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Client,
) -> Result<TestClientModelResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Client,
) -> Result<TestClientModelResponse, E>;
/// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트.
///
/// TestEndpointParameters - POST /v2/fake
async fn test_endpoint_parameters(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::TestEndpointParametersRequest,
) -> Result<TestEndpointParametersResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::TestEndpointParametersRequest,
) -> Result<TestEndpointParametersResponse, E>;
/// To test enum parameters.
///
/// TestEnumParameters - GET /v2/fake
async fn test_enum_parameters(
&self,
method: Method,
host: Host,
cookies: CookieJar,
header_params: models::TestEnumParametersHeaderParams,
query_params: models::TestEnumParametersQueryParams,
body: Option<models::TestEnumParametersRequest>,
) -> Result<TestEnumParametersResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
header_params: &models::TestEnumParametersHeaderParams,
query_params: &models::TestEnumParametersQueryParams,
body: &Option<models::TestEnumParametersRequest>,
) -> Result<TestEnumParametersResponse, E>;
/// test inline additionalProperties.
///
/// TestInlineAdditionalProperties - POST /v2/fake/inline-additionalProperties
async fn test_inline_additional_properties(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: std::collections::HashMap<String, String>,
) -> Result<TestInlineAdditionalPropertiesResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &std::collections::HashMap<String, String>,
) -> Result<TestInlineAdditionalPropertiesResponse, E>;
/// test json serialization of form data.
///
/// TestJsonFormData - GET /v2/fake/jsonFormData
async fn test_json_form_data(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::TestJsonFormDataRequest,
) -> Result<TestJsonFormDataResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::TestJsonFormDataRequest,
) -> Result<TestJsonFormDataResponse, E>;
}

View File

@ -18,15 +18,17 @@ pub enum TestClassnameResponse {
/// FakeClassnameTags123
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait FakeClassnameTags123 {
pub trait FakeClassnameTags123<E: std::fmt::Debug + Send + Sync + 'static = ()>:
super::ErrorHandler<E>
{
/// To test class name in snake case.
///
/// TestClassname - PATCH /v2/fake_classname_test
async fn test_classname(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Client,
) -> Result<TestClassnameResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Client,
) -> Result<TestClassnameResponse, E>;
}

View File

@ -17,3 +17,23 @@ pub trait ApiKeyAuthHeader {
key: &str,
) -> Option<Self::Claims>;
}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -86,7 +86,7 @@ pub enum UploadFileResponse {
/// Pet
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Pet {
pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
type Claims;
/// Add a new pet to the store.
@ -94,90 +94,90 @@ pub trait Pet {
/// AddPet - POST /v2/pet
async fn add_pet(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Pet,
) -> Result<AddPetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Pet,
) -> Result<AddPetResponse, E>;
/// Deletes a pet.
///
/// DeletePet - DELETE /v2/pet/{petId}
async fn delete_pet(
&self,
method: Method,
host: Host,
cookies: CookieJar,
header_params: models::DeletePetHeaderParams,
path_params: models::DeletePetPathParams,
) -> Result<DeletePetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
header_params: &models::DeletePetHeaderParams,
path_params: &models::DeletePetPathParams,
) -> Result<DeletePetResponse, E>;
/// Finds Pets by status.
///
/// FindPetsByStatus - GET /v2/pet/findByStatus
async fn find_pets_by_status(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::FindPetsByStatusQueryParams,
) -> Result<FindPetsByStatusResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::FindPetsByStatusQueryParams,
) -> Result<FindPetsByStatusResponse, E>;
/// Finds Pets by tags.
///
/// FindPetsByTags - GET /v2/pet/findByTags
async fn find_pets_by_tags(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::FindPetsByTagsQueryParams,
) -> Result<FindPetsByTagsResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::FindPetsByTagsQueryParams,
) -> Result<FindPetsByTagsResponse, E>;
/// Find pet by ID.
///
/// GetPetById - GET /v2/pet/{petId}
async fn get_pet_by_id(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
path_params: models::GetPetByIdPathParams,
) -> Result<GetPetByIdResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
path_params: &models::GetPetByIdPathParams,
) -> Result<GetPetByIdResponse, E>;
/// Update an existing pet.
///
/// UpdatePet - PUT /v2/pet
async fn update_pet(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Pet,
) -> Result<UpdatePetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Pet,
) -> Result<UpdatePetResponse, E>;
/// Updates a pet in the store with form data.
///
/// UpdatePetWithForm - POST /v2/pet/{petId}
async fn update_pet_with_form(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::UpdatePetWithFormPathParams,
body: Option<models::UpdatePetWithFormRequest>,
) -> Result<UpdatePetWithFormResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::UpdatePetWithFormPathParams,
body: &Option<models::UpdatePetWithFormRequest>,
) -> Result<UpdatePetWithFormResponse, E>;
/// uploads an image.
///
/// UploadFile - POST /v2/pet/{petId}/uploadImage
async fn upload_file(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::UploadFilePathParams,
body: Multipart,
) -> Result<UploadFileResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::UploadFilePathParams,
body: &Multipart,
) -> Result<UploadFileResponse, E>;
}

View File

@ -50,7 +50,7 @@ pub enum PlaceOrderResponse {
/// Store
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Store {
pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
type Claims;
/// Delete purchase order by ID.
@ -58,42 +58,42 @@ pub trait Store {
/// DeleteOrder - DELETE /v2/store/order/{order_id}
async fn delete_order(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::DeleteOrderPathParams,
) -> Result<DeleteOrderResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::DeleteOrderPathParams,
) -> Result<DeleteOrderResponse, E>;
/// Returns pet inventories by status.
///
/// GetInventory - GET /v2/store/inventory
async fn get_inventory(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
) -> Result<GetInventoryResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
) -> Result<GetInventoryResponse, E>;
/// Find purchase order by ID.
///
/// GetOrderById - GET /v2/store/order/{order_id}
async fn get_order_by_id(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::GetOrderByIdPathParams,
) -> Result<GetOrderByIdResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::GetOrderByIdPathParams,
) -> Result<GetOrderByIdResponse, E>;
/// Place an order for a pet.
///
/// PlaceOrder - POST /v2/store/order
async fn place_order(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Order,
) -> Result<PlaceOrderResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Order,
) -> Result<PlaceOrderResponse, E>;
}

View File

@ -88,92 +88,92 @@ pub enum UpdateUserResponse {
/// User
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait User {
pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// Create user.
///
/// CreateUser - POST /v2/user
async fn create_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::User,
) -> Result<CreateUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::User,
) -> Result<CreateUserResponse, E>;
/// Creates list of users with given input array.
///
/// CreateUsersWithArrayInput - POST /v2/user/createWithArray
async fn create_users_with_array_input(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Vec<models::User>,
) -> Result<CreateUsersWithArrayInputResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Vec<models::User>,
) -> Result<CreateUsersWithArrayInputResponse, E>;
/// Creates list of users with given input array.
///
/// CreateUsersWithListInput - POST /v2/user/createWithList
async fn create_users_with_list_input(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: Vec<models::User>,
) -> Result<CreateUsersWithListInputResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &Vec<models::User>,
) -> Result<CreateUsersWithListInputResponse, E>;
/// Delete user.
///
/// DeleteUser - DELETE /v2/user/{username}
async fn delete_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::DeleteUserPathParams,
) -> Result<DeleteUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::DeleteUserPathParams,
) -> Result<DeleteUserResponse, E>;
/// Get user by user name.
///
/// GetUserByName - GET /v2/user/{username}
async fn get_user_by_name(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::GetUserByNamePathParams,
) -> Result<GetUserByNameResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::GetUserByNamePathParams,
) -> Result<GetUserByNameResponse, E>;
/// Logs user into the system.
///
/// LoginUser - GET /v2/user/login
async fn login_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::LoginUserQueryParams,
) -> Result<LoginUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::LoginUserQueryParams,
) -> Result<LoginUserResponse, E>;
/// Logs out current logged in user session.
///
/// LogoutUser - GET /v2/user/logout
async fn logout_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<LogoutUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<LogoutUserResponse, E>;
/// Updated user.
///
/// UpdateUser - PUT /v2/user/{username}
async fn update_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::UpdateUserPathParams,
body: models::User,
) -> Result<UpdateUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::UpdateUserPathParams,
body: &models::User,
) -> Result<UpdateUserResponse, E>;
}

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -41,7 +41,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 1.0.0
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,10 +43,12 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl petstore::Api for ServerImpl {
impl petstore::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl petstore::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();

View File

@ -14,3 +14,23 @@ pub trait ApiKeyAuthHeader {
key: &str,
) -> Option<Self::Claims>;
}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -90,7 +90,7 @@ pub enum UploadFileResponse {
/// Pet
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Pet {
pub trait Pet<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
type Claims;
/// Add a new pet to the store.
@ -98,90 +98,90 @@ pub trait Pet {
/// AddPet - POST /v2/pet
async fn add_pet(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Pet,
) -> Result<AddPetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Pet,
) -> Result<AddPetResponse, E>;
/// Deletes a pet.
///
/// DeletePet - DELETE /v2/pet/{petId}
async fn delete_pet(
&self,
method: Method,
host: Host,
cookies: CookieJar,
header_params: models::DeletePetHeaderParams,
path_params: models::DeletePetPathParams,
) -> Result<DeletePetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
header_params: &models::DeletePetHeaderParams,
path_params: &models::DeletePetPathParams,
) -> Result<DeletePetResponse, E>;
/// Finds Pets by status.
///
/// FindPetsByStatus - GET /v2/pet/findByStatus
async fn find_pets_by_status(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::FindPetsByStatusQueryParams,
) -> Result<FindPetsByStatusResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::FindPetsByStatusQueryParams,
) -> Result<FindPetsByStatusResponse, E>;
/// Finds Pets by tags.
///
/// FindPetsByTags - GET /v2/pet/findByTags
async fn find_pets_by_tags(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::FindPetsByTagsQueryParams,
) -> Result<FindPetsByTagsResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::FindPetsByTagsQueryParams,
) -> Result<FindPetsByTagsResponse, E>;
/// Find pet by ID.
///
/// GetPetById - GET /v2/pet/{petId}
async fn get_pet_by_id(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
path_params: models::GetPetByIdPathParams,
) -> Result<GetPetByIdResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
path_params: &models::GetPetByIdPathParams,
) -> Result<GetPetByIdResponse, E>;
/// Update an existing pet.
///
/// UpdatePet - PUT /v2/pet
async fn update_pet(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Pet,
) -> Result<UpdatePetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Pet,
) -> Result<UpdatePetResponse, E>;
/// Updates a pet in the store with form data.
///
/// UpdatePetWithForm - POST /v2/pet/{petId}
async fn update_pet_with_form(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::UpdatePetWithFormPathParams,
body: Option<models::UpdatePetWithFormRequest>,
) -> Result<UpdatePetWithFormResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::UpdatePetWithFormPathParams,
body: &Option<models::UpdatePetWithFormRequest>,
) -> Result<UpdatePetWithFormResponse, E>;
/// uploads an image.
///
/// UploadFile - POST /v2/pet/{petId}/uploadImage
async fn upload_file(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::UploadFilePathParams,
body: Multipart,
) -> Result<UploadFileResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::UploadFilePathParams,
body: &Multipart,
) -> Result<UploadFileResponse, E>;
}

View File

@ -50,7 +50,7 @@ pub enum PlaceOrderResponse {
/// Store
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Store {
pub trait Store<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
type Claims;
/// Delete purchase order by ID.
@ -58,42 +58,42 @@ pub trait Store {
/// DeleteOrder - DELETE /v2/store/order/{orderId}
async fn delete_order(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::DeleteOrderPathParams,
) -> Result<DeleteOrderResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::DeleteOrderPathParams,
) -> Result<DeleteOrderResponse, E>;
/// Returns pet inventories by status.
///
/// GetInventory - GET /v2/store/inventory
async fn get_inventory(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
) -> Result<GetInventoryResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
) -> Result<GetInventoryResponse, E>;
/// Find purchase order by ID.
///
/// GetOrderById - GET /v2/store/order/{orderId}
async fn get_order_by_id(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::GetOrderByIdPathParams,
) -> Result<GetOrderByIdResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::GetOrderByIdPathParams,
) -> Result<GetOrderByIdResponse, E>;
/// Place an order for a pet.
///
/// PlaceOrder - POST /v2/store/order
async fn place_order(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Order,
) -> Result<PlaceOrderResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Order,
) -> Result<PlaceOrderResponse, E>;
}

View File

@ -89,7 +89,7 @@ pub enum UpdateUserResponse {
/// User
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait User {
pub trait User<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
type Claims;
/// Create user.
@ -97,92 +97,92 @@ pub trait User {
/// CreateUser - POST /v2/user
async fn create_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
body: models::User,
) -> Result<CreateUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
body: &models::User,
) -> Result<CreateUserResponse, E>;
/// Creates list of users with given input array.
///
/// CreateUsersWithArrayInput - POST /v2/user/createWithArray
async fn create_users_with_array_input(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
body: Vec<models::User>,
) -> Result<CreateUsersWithArrayInputResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
body: &Vec<models::User>,
) -> Result<CreateUsersWithArrayInputResponse, E>;
/// Creates list of users with given input array.
///
/// CreateUsersWithListInput - POST /v2/user/createWithList
async fn create_users_with_list_input(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
body: Vec<models::User>,
) -> Result<CreateUsersWithListInputResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
body: &Vec<models::User>,
) -> Result<CreateUsersWithListInputResponse, E>;
/// Delete user.
///
/// DeleteUser - DELETE /v2/user/{username}
async fn delete_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
path_params: models::DeleteUserPathParams,
) -> Result<DeleteUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
path_params: &models::DeleteUserPathParams,
) -> Result<DeleteUserResponse, E>;
/// Get user by user name.
///
/// GetUserByName - GET /v2/user/{username}
async fn get_user_by_name(
&self,
method: Method,
host: Host,
cookies: CookieJar,
path_params: models::GetUserByNamePathParams,
) -> Result<GetUserByNameResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
path_params: &models::GetUserByNamePathParams,
) -> Result<GetUserByNameResponse, E>;
/// Logs user into the system.
///
/// LoginUser - GET /v2/user/login
async fn login_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
query_params: models::LoginUserQueryParams,
) -> Result<LoginUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
query_params: &models::LoginUserQueryParams,
) -> Result<LoginUserResponse, E>;
/// Logs out current logged in user session.
///
/// LogoutUser - GET /v2/user/logout
async fn logout_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
) -> Result<LogoutUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
) -> Result<LogoutUserResponse, E>;
/// Updated user.
///
/// UpdateUser - PUT /v2/user/{username}
async fn update_user(
&self,
method: Method,
host: Host,
cookies: CookieJar,
claims: Self::Claims,
path_params: models::UpdateUserPathParams,
body: models::User,
) -> Result<UpdateUserResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
path_params: &models::UpdateUserPathParams,
body: &models::User,
) -> Result<UpdateUserResponse, E>;
}

View File

@ -13,54 +13,63 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A, C>(api_impl: I) -> Router
pub fn new<I, A, E, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::pet::Pet<Claims = C>
+ apis::store::Store<Claims = C>
+ apis::user::User<Claims = C>
A: apis::pet::Pet<E, Claims = C>
+ apis::store::Store<E, Claims = C>
+ apis::user::User<E, Claims = C>
+ apis::ApiKeyAuthHeader<Claims = C>
+ Send
+ Sync
+ 'static,
E: std::fmt::Debug + Send + Sync + 'static,
C: Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route(
"/v2/pet",
post(add_pet::<I, A, C>).put(update_pet::<I, A, C>),
post(add_pet::<I, A, E, C>).put(update_pet::<I, A, E, C>),
)
.route(
"/v2/pet/:pet_id",
delete(delete_pet::<I, A, C>)
.get(get_pet_by_id::<I, A, C>)
.post(update_pet_with_form::<I, A, C>),
delete(delete_pet::<I, A, E, C>)
.get(get_pet_by_id::<I, A, E, C>)
.post(update_pet_with_form::<I, A, E, C>),
)
.route("/v2/pet/:pet_id/uploadImage", post(upload_file::<I, A, C>))
.route("/v2/pet/findByStatus", get(find_pets_by_status::<I, A, C>))
.route("/v2/pet/findByTags", get(find_pets_by_tags::<I, A, C>))
.route("/v2/store/inventory", get(get_inventory::<I, A, C>))
.route("/v2/store/order", post(place_order::<I, A, C>))
.route(
"/v2/pet/:pet_id/uploadImage",
post(upload_file::<I, A, E, C>),
)
.route(
"/v2/pet/findByStatus",
get(find_pets_by_status::<I, A, E, C>),
)
.route("/v2/pet/findByTags", get(find_pets_by_tags::<I, A, E, C>))
.route("/v2/store/inventory", get(get_inventory::<I, A, E, C>))
.route("/v2/store/order", post(place_order::<I, A, E, C>))
.route(
"/v2/store/order/:order_id",
delete(delete_order::<I, A, C>).get(get_order_by_id::<I, A, C>),
delete(delete_order::<I, A, E, C>).get(get_order_by_id::<I, A, E, C>),
)
.route("/v2/user", post(create_user::<I, A, C>))
.route("/v2/user", post(create_user::<I, A, E, C>))
.route(
"/v2/user/:username",
delete(delete_user::<I, A, C>)
.get(get_user_by_name::<I, A, C>)
.put(update_user::<I, A, C>),
delete(delete_user::<I, A, E, C>)
.get(get_user_by_name::<I, A, E, C>)
.put(update_user::<I, A, E, C>),
)
.route(
"/v2/user/createWithArray",
post(create_users_with_array_input::<I, A, C>),
post(create_users_with_array_input::<I, A, E, C>),
)
.route(
"/v2/user/createWithList",
post(create_users_with_list_input::<I, A, C>),
post(create_users_with_list_input::<I, A, E, C>),
)
.route("/v2/user/login", get(login_user::<I, A, C>))
.route("/v2/user/logout", get(logout_user::<I, A, C>))
.route("/v2/user/login", get(login_user::<I, A, E, C>))
.route("/v2/user/logout", get(logout_user::<I, A, E, C>))
.with_state(api_impl)
}
@ -80,7 +89,7 @@ fn add_pet_validation(body: models::Pet) -> std::result::Result<(models::Pet,),
}
/// AddPet - POST /v2/pet
#[tracing::instrument(skip_all)]
async fn add_pet<I, A, C>(
async fn add_pet<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -89,7 +98,8 @@ async fn add_pet<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || add_pet_validation(body))
@ -103,7 +113,10 @@ where
.map_err(|_| StatusCode::BAD_REQUEST);
};
let result = api_impl.as_ref().add_pet(method, host, cookies, body).await;
let result = api_impl
.as_ref()
.add_pet(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -130,10 +143,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -158,7 +175,7 @@ fn delete_pet_validation(
}
/// DeletePet - DELETE /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn delete_pet<I, A, C>(
async fn delete_pet<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -168,7 +185,8 @@ async fn delete_pet<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Header parameters
let header_params = {
@ -210,7 +228,7 @@ where
let result = api_impl
.as_ref()
.delete_pet(method, host, cookies, header_params, path_params)
.delete_pet(&method, &host, &cookies, &header_params, &path_params)
.await;
let mut response = Response::builder();
@ -222,10 +240,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -245,7 +267,7 @@ fn find_pets_by_status_validation(
}
/// FindPetsByStatus - GET /v2/pet/findByStatus
#[tracing::instrument(skip_all)]
async fn find_pets_by_status<I, A, C>(
async fn find_pets_by_status<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -254,7 +276,8 @@ async fn find_pets_by_status<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -271,7 +294,7 @@ where
let result = api_impl
.as_ref()
.find_pets_by_status(method, host, cookies, query_params)
.find_pets_by_status(&method, &host, &cookies, &query_params)
.await;
let mut response = Response::builder();
@ -299,10 +322,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -322,7 +349,7 @@ fn find_pets_by_tags_validation(
}
/// FindPetsByTags - GET /v2/pet/findByTags
#[tracing::instrument(skip_all)]
async fn find_pets_by_tags<I, A, C>(
async fn find_pets_by_tags<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -331,7 +358,8 @@ async fn find_pets_by_tags<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -348,7 +376,7 @@ where
let result = api_impl
.as_ref()
.find_pets_by_tags(method, host, cookies, query_params)
.find_pets_by_tags(&method, &host, &cookies, &query_params)
.await;
let mut response = Response::builder();
@ -376,10 +404,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -399,7 +431,7 @@ fn get_pet_by_id_validation(
}
/// GetPetById - GET /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn get_pet_by_id<I, A, C>(
async fn get_pet_by_id<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -409,7 +441,8 @@ async fn get_pet_by_id<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -438,7 +471,7 @@ where
let result = api_impl
.as_ref()
.get_pet_by_id(method, host, cookies, claims, path_params)
.get_pet_by_id(&method, &host, &cookies, &claims, &path_params)
.await;
let mut response = Response::builder();
@ -470,10 +503,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -501,7 +538,7 @@ fn update_pet_validation(
}
/// UpdatePet - PUT /v2/pet
#[tracing::instrument(skip_all)]
async fn update_pet<I, A, C>(
async fn update_pet<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -510,7 +547,8 @@ async fn update_pet<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || update_pet_validation(body))
@ -526,7 +564,7 @@ where
let result = api_impl
.as_ref()
.update_pet(method, host, cookies, body)
.update_pet(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -562,10 +600,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -603,7 +645,7 @@ fn update_pet_with_form_validation(
}
/// UpdatePetWithForm - POST /v2/pet/{petId}
#[tracing::instrument(skip_all)]
async fn update_pet_with_form<I, A, C>(
async fn update_pet_with_form<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -613,7 +655,8 @@ async fn update_pet_with_form<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation =
@ -630,7 +673,7 @@ where
let result = api_impl
.as_ref()
.update_pet_with_form(method, host, cookies, path_params, body)
.update_pet_with_form(&method, &host, &cookies, &path_params, &body)
.await;
let mut response = Response::builder();
@ -642,10 +685,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -665,7 +712,7 @@ fn upload_file_validation(
}
/// UploadFile - POST /v2/pet/{petId}/uploadImage
#[tracing::instrument(skip_all)]
async fn upload_file<I, A, C>(
async fn upload_file<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -675,7 +722,8 @@ async fn upload_file<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::pet::Pet<Claims = C>,
A: apis::pet::Pet<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || upload_file_validation(path_params))
@ -691,7 +739,7 @@ where
let result = api_impl
.as_ref()
.upload_file(method, host, cookies, path_params, body)
.upload_file(&method, &host, &cookies, &path_params, &body)
.await;
let mut response = Response::builder();
@ -722,10 +770,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -745,7 +797,7 @@ fn delete_order_validation(
}
/// DeleteOrder - DELETE /v2/store/order/{orderId}
#[tracing::instrument(skip_all)]
async fn delete_order<I, A, C>(
async fn delete_order<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -754,7 +806,8 @@ async fn delete_order<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store<Claims = C>,
A: apis::store::Store<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || delete_order_validation(path_params))
@ -770,7 +823,7 @@ where
let result = api_impl
.as_ref()
.delete_order(method, host, cookies, path_params)
.delete_order(&method, &host, &cookies, &path_params)
.await;
let mut response = Response::builder();
@ -786,10 +839,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -805,7 +862,7 @@ fn get_inventory_validation() -> std::result::Result<(), ValidationErrors> {
}
/// GetInventory - GET /v2/store/inventory
#[tracing::instrument(skip_all)]
async fn get_inventory<I, A, C>(
async fn get_inventory<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -814,7 +871,8 @@ async fn get_inventory<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::store::Store<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -843,7 +901,7 @@ where
let result = api_impl
.as_ref()
.get_inventory(method, host, cookies, claims)
.get_inventory(&method, &host, &cookies, &claims)
.await;
let mut response = Response::builder();
@ -874,10 +932,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -897,7 +959,7 @@ fn get_order_by_id_validation(
}
/// GetOrderById - GET /v2/store/order/{orderId}
#[tracing::instrument(skip_all)]
async fn get_order_by_id<I, A, C>(
async fn get_order_by_id<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -906,7 +968,8 @@ async fn get_order_by_id<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store<Claims = C>,
A: apis::store::Store<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_order_by_id_validation(path_params))
@ -922,7 +985,7 @@ where
let result = api_impl
.as_ref()
.get_order_by_id(method, host, cookies, path_params)
.get_order_by_id(&method, &host, &cookies, &path_params)
.await;
let mut response = Response::builder();
@ -954,10 +1017,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -985,7 +1052,7 @@ fn place_order_validation(
}
/// PlaceOrder - POST /v2/store/order
#[tracing::instrument(skip_all)]
async fn place_order<I, A, C>(
async fn place_order<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -994,7 +1061,8 @@ async fn place_order<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::store::Store<Claims = C>,
A: apis::store::Store<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || place_order_validation(body))
@ -1010,7 +1078,7 @@ where
let result = api_impl
.as_ref()
.place_order(method, host, cookies, body)
.place_order(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -1038,10 +1106,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1069,7 +1141,7 @@ fn create_user_validation(
}
/// CreateUser - POST /v2/user
#[tracing::instrument(skip_all)]
async fn create_user<I, A, C>(
async fn create_user<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1079,7 +1151,8 @@ async fn create_user<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::user::User<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -1108,7 +1181,7 @@ where
let result = api_impl
.as_ref()
.create_user(method, host, cookies, claims, body)
.create_user(&method, &host, &cookies, &claims, &body)
.await;
let mut response = Response::builder();
@ -1120,10 +1193,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1151,7 +1228,7 @@ fn create_users_with_array_input_validation(
}
/// CreateUsersWithArrayInput - POST /v2/user/createWithArray
#[tracing::instrument(skip_all)]
async fn create_users_with_array_input<I, A, C>(
async fn create_users_with_array_input<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1161,7 +1238,8 @@ async fn create_users_with_array_input<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::user::User<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -1191,7 +1269,7 @@ where
let result = api_impl
.as_ref()
.create_users_with_array_input(method, host, cookies, claims, body)
.create_users_with_array_input(&method, &host, &cookies, &claims, &body)
.await;
let mut response = Response::builder();
@ -1203,10 +1281,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1234,7 +1316,7 @@ fn create_users_with_list_input_validation(
}
/// CreateUsersWithListInput - POST /v2/user/createWithList
#[tracing::instrument(skip_all)]
async fn create_users_with_list_input<I, A, C>(
async fn create_users_with_list_input<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1244,7 +1326,8 @@ async fn create_users_with_list_input<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::user::User<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -1274,7 +1357,7 @@ where
let result = api_impl
.as_ref()
.create_users_with_list_input(method, host, cookies, claims, body)
.create_users_with_list_input(&method, &host, &cookies, &claims, &body)
.await;
let mut response = Response::builder();
@ -1286,10 +1369,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1309,7 +1396,7 @@ fn delete_user_validation(
}
/// DeleteUser - DELETE /v2/user/{username}
#[tracing::instrument(skip_all)]
async fn delete_user<I, A, C>(
async fn delete_user<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1319,7 +1406,8 @@ async fn delete_user<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::user::User<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -1348,7 +1436,7 @@ where
let result = api_impl
.as_ref()
.delete_user(method, host, cookies, claims, path_params)
.delete_user(&method, &host, &cookies, &claims, &path_params)
.await;
let mut response = Response::builder();
@ -1364,10 +1452,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1387,7 +1479,7 @@ fn get_user_by_name_validation(
}
/// GetUserByName - GET /v2/user/{username}
#[tracing::instrument(skip_all)]
async fn get_user_by_name<I, A, C>(
async fn get_user_by_name<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1396,7 +1488,8 @@ async fn get_user_by_name<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C>,
A: apis::user::User<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_user_by_name_validation(path_params))
@ -1412,7 +1505,7 @@ where
let result = api_impl
.as_ref()
.get_user_by_name(method, host, cookies, path_params)
.get_user_by_name(&method, &host, &cookies, &path_params)
.await;
let mut response = Response::builder();
@ -1444,10 +1537,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1467,7 +1564,7 @@ fn login_user_validation(
}
/// LoginUser - GET /v2/user/login
#[tracing::instrument(skip_all)]
async fn login_user<I, A, C>(
async fn login_user<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1476,7 +1573,8 @@ async fn login_user<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C>,
A: apis::user::User<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || login_user_validation(query_params))
@ -1492,7 +1590,7 @@ where
let result = api_impl
.as_ref()
.login_user(method, host, cookies, query_params)
.login_user(&method, &host, &cookies, &query_params)
.await;
let mut response = Response::builder();
@ -1573,10 +1671,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1592,7 +1694,7 @@ fn logout_user_validation() -> std::result::Result<(), ValidationErrors> {
}
/// LogoutUser - GET /v2/user/logout
#[tracing::instrument(skip_all)]
async fn logout_user<I, A, C>(
async fn logout_user<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1601,7 +1703,8 @@ async fn logout_user<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::user::User<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -1630,7 +1733,7 @@ where
let result = api_impl
.as_ref()
.logout_user(method, host, cookies, claims)
.logout_user(&method, &host, &cookies, &claims)
.await;
let mut response = Response::builder();
@ -1642,10 +1745,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -1675,7 +1782,7 @@ fn update_user_validation(
}
/// UpdateUser - PUT /v2/user/{username}
#[tracing::instrument(skip_all)]
async fn update_user<I, A, C>(
async fn update_user<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1686,7 +1793,8 @@ async fn update_user<I, A, C>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::user::User<Claims = C> + apis::ApiKeyAuthHeader<Claims = C>,
A: apis::user::User<E, Claims = C> + apis::ApiKeyAuthHeader<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_header = api_impl
@ -1715,7 +1823,7 @@ where
let result = api_impl
.as_ref()
.update_user(method, host, cookies, claims, path_params, body)
.update_user(&method, &host, &cookies, &claims, &path_params, &body)
.await;
let mut response = Response::builder();
@ -1731,10 +1839,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 1.0
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl ping-bearer-auth::Api for ServerImpl {
impl ping_bearer_auth::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl ping_bearer_auth::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = ping-bearer-auth::server::new(Arc::new(ServerImpl));
let app = ping_bearer_auth::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -18,12 +18,12 @@ pub enum PingGetResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// PingGet - GET /ping
async fn ping_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<PingGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<PingGetResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -13,14 +13,15 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, E>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::default::Default + 'static,
A: apis::default::Default<E> + Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/ping", get(ping_get::<I, A>))
.route("/ping", get(ping_get::<I, A, E>))
.with_state(api_impl)
}
@ -30,7 +31,7 @@ fn ping_get_validation() -> std::result::Result<(), ValidationErrors> {
}
/// PingGet - GET /ping
#[tracing::instrument(skip_all)]
async fn ping_get<I, A>(
async fn ping_get<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -38,7 +39,8 @@ async fn ping_get<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || ping_get_validation())
@ -52,7 +54,7 @@ where
.map_err(|_| StatusCode::BAD_REQUEST);
};
let result = api_impl.as_ref().ping_get(method, host, cookies).await;
let result = api_impl.as_ref().ping_get(&method, &host, &cookies).await;
let mut response = Response::builder();
@ -63,10 +65,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 0.1.9
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl rust-axum-header-uui::Api for ServerImpl {
impl rust_axum_header_uui::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl rust_axum_header_uui::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = rust-axum-header-uui::server::new(Arc::new(ServerImpl));
let app = rust_axum_header_uui::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -18,13 +18,13 @@ pub enum UsersPostResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// UsersPost - POST /users
async fn users_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
header_params: models::UsersPostHeaderParams,
) -> Result<UsersPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
header_params: &models::UsersPostHeaderParams,
) -> Result<UsersPostResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -13,14 +13,15 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, E>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::default::Default + 'static,
A: apis::default::Default<E> + Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/users", post(users_post::<I, A>))
.route("/users", post(users_post::<I, A, E>))
.with_state(api_impl)
}
@ -34,7 +35,7 @@ fn users_post_validation(
}
/// UsersPost - POST /users
#[tracing::instrument(skip_all)]
async fn users_post<I, A>(
async fn users_post<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -43,7 +44,8 @@ async fn users_post<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Header parameters
let header_params = {
@ -92,7 +94,7 @@ where
let result = api_impl
.as_ref()
.users_post(method, host, cookies, header_params)
.users_post(&method, &host, &cookies, &header_params)
.await;
let mut response = Response::builder();
@ -123,10 +125,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 0.0.1
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl rust-axum-oneof::Api for ServerImpl {
impl rust_axum_oneof::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl rust_axum_oneof::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = rust-axum-oneof::server::new(Arc::new(ServerImpl));
let app = rust_axum_oneof::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -18,13 +18,13 @@ pub enum FooResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// Foo - POST /
async fn foo(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Message,
) -> Result<FooResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Message,
) -> Result<FooResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -13,14 +13,15 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, E>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::default::Default + 'static,
A: apis::default::Default<E> + Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/", post(foo::<I, A>))
.route("/", post(foo::<I, A, E>))
.with_state(api_impl)
}
@ -42,7 +43,7 @@ fn foo_validation(
}
/// Foo - POST /
#[tracing::instrument(skip_all)]
async fn foo<I, A>(
async fn foo<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -51,7 +52,8 @@ async fn foo<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || foo_validation(body))
@ -65,7 +67,7 @@ where
.map_err(|_| StatusCode::BAD_REQUEST);
};
let result = api_impl.as_ref().foo(method, host, cookies, body).await;
let result = api_impl.as_ref().foo(&method, &host, &cookies, &body).await;
let mut response = Response::builder();
@ -95,10 +97,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -1 +1 @@
7.11.0-SNAPSHOT
7.12.0-SNAPSHOT

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 2.3.4
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl rust-server-test::Api for ServerImpl {
impl rust_server_test::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl rust_server_test::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = rust-server-test::server::new(Arc::new(ServerImpl));
let app = rust_server_test::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -82,90 +82,90 @@ pub enum SoloObjectPostResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// AllOfGet - GET /allOf
async fn all_of_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<AllOfGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<AllOfGetResponse, E>;
/// A dummy endpoint to make the spec valid..
///
/// DummyGet - GET /dummy
async fn dummy_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<DummyGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<DummyGetResponse, E>;
/// DummyPut - PUT /dummy
async fn dummy_put(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::FooDummyPutRequest,
) -> Result<DummyPutResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::FooDummyPutRequest,
) -> Result<DummyPutResponse, E>;
/// Get a file.
///
/// FileResponseGet - GET /file_response
async fn file_response_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<FileResponseGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<FileResponseGetResponse, E>;
/// GetStructuredYaml - GET /get-structured-yaml
async fn get_structured_yaml(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<GetStructuredYamlResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<GetStructuredYamlResponse, E>;
/// Test HTML handling.
///
/// HtmlPost - POST /html
async fn html_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: String,
) -> Result<HtmlPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &String,
) -> Result<HtmlPostResponse, E>;
/// PostYaml - POST /post-yaml
async fn post_yaml(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: String,
) -> Result<PostYamlResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &String,
) -> Result<PostYamlResponse, E>;
/// Get an arbitrary JSON blob..
///
/// RawJsonGet - GET /raw_json
async fn raw_json_get(
&self,
method: Method,
host: Host,
cookies: CookieJar,
) -> Result<RawJsonGetResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
) -> Result<RawJsonGetResponse, E>;
/// Send an arbitrary JSON blob.
///
/// SoloObjectPost - POST /solo-object
async fn solo_object_post(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: crate::types::Object,
) -> Result<SoloObjectPostResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &crate::types::Object,
) -> Result<SoloObjectPostResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -13,21 +13,25 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, E>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::default::Default + 'static,
A: apis::default::Default<E> + Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/allOf", get(all_of_get::<I, A>))
.route("/dummy", get(dummy_get::<I, A>).put(dummy_put::<I, A>))
.route("/file_response", get(file_response_get::<I, A>))
.route("/get-structured-yaml", get(get_structured_yaml::<I, A>))
.route("/html", post(html_post::<I, A>))
.route("/post-yaml", post(post_yaml::<I, A>))
.route("/raw_json", get(raw_json_get::<I, A>))
.route("/solo-object", post(solo_object_post::<I, A>))
.route("/allOf", get(all_of_get::<I, A, E>))
.route(
"/dummy",
get(dummy_get::<I, A, E>).put(dummy_put::<I, A, E>),
)
.route("/file_response", get(file_response_get::<I, A, E>))
.route("/get-structured-yaml", get(get_structured_yaml::<I, A, E>))
.route("/html", post(html_post::<I, A, E>))
.route("/post-yaml", post(post_yaml::<I, A, E>))
.route("/raw_json", get(raw_json_get::<I, A, E>))
.route("/solo-object", post(solo_object_post::<I, A, E>))
.with_state(api_impl)
}
@ -37,7 +41,7 @@ fn all_of_get_validation() -> std::result::Result<(), ValidationErrors> {
}
/// AllOfGet - GET /allOf
#[tracing::instrument(skip_all)]
async fn all_of_get<I, A>(
async fn all_of_get<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -45,7 +49,8 @@ async fn all_of_get<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || all_of_get_validation())
@ -59,7 +64,7 @@ where
.map_err(|_| StatusCode::BAD_REQUEST);
};
let result = api_impl.as_ref().all_of_get(method, host, cookies).await;
let result = api_impl.as_ref().all_of_get(&method, &host, &cookies).await;
let mut response = Response::builder();
@ -89,10 +94,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -108,7 +117,7 @@ fn dummy_get_validation() -> std::result::Result<(), ValidationErrors> {
}
/// DummyGet - GET /dummy
#[tracing::instrument(skip_all)]
async fn dummy_get<I, A>(
async fn dummy_get<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -116,7 +125,8 @@ async fn dummy_get<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || dummy_get_validation())
@ -130,7 +140,7 @@ where
.map_err(|_| StatusCode::BAD_REQUEST);
};
let result = api_impl.as_ref().dummy_get(method, host, cookies).await;
let result = api_impl.as_ref().dummy_get(&method, &host, &cookies).await;
let mut response = Response::builder();
@ -141,10 +151,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -172,7 +186,7 @@ fn dummy_put_validation(
}
/// DummyPut - PUT /dummy
#[tracing::instrument(skip_all)]
async fn dummy_put<I, A>(
async fn dummy_put<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -181,7 +195,8 @@ async fn dummy_put<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || dummy_put_validation(body))
@ -197,7 +212,7 @@ where
let result = api_impl
.as_ref()
.dummy_put(method, host, cookies, body)
.dummy_put(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -209,10 +224,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -228,7 +247,7 @@ fn file_response_get_validation() -> std::result::Result<(), ValidationErrors> {
}
/// FileResponseGet - GET /file_response
#[tracing::instrument(skip_all)]
async fn file_response_get<I, A>(
async fn file_response_get<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -236,7 +255,8 @@ async fn file_response_get<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || file_response_get_validation())
@ -252,7 +272,7 @@ where
let result = api_impl
.as_ref()
.file_response_get(method, host, cookies)
.file_response_get(&method, &host, &cookies)
.await;
let mut response = Response::builder();
@ -283,10 +303,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -302,7 +326,7 @@ fn get_structured_yaml_validation() -> std::result::Result<(), ValidationErrors>
}
/// GetStructuredYaml - GET /get-structured-yaml
#[tracing::instrument(skip_all)]
async fn get_structured_yaml<I, A>(
async fn get_structured_yaml<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -310,7 +334,8 @@ async fn get_structured_yaml<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_structured_yaml_validation())
@ -326,7 +351,7 @@ where
let result = api_impl
.as_ref()
.get_structured_yaml(method, host, cookies)
.get_structured_yaml(&method, &host, &cookies)
.await;
let mut response = Response::builder();
@ -350,10 +375,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -375,7 +404,7 @@ fn html_post_validation(body: String) -> std::result::Result<(String,), Validati
}
/// HtmlPost - POST /html
#[tracing::instrument(skip_all)]
async fn html_post<I, A>(
async fn html_post<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -384,7 +413,8 @@ async fn html_post<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || html_post_validation(body))
@ -400,7 +430,7 @@ where
let result = api_impl
.as_ref()
.html_post(method, host, cookies, body)
.html_post(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -424,10 +454,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -449,7 +483,7 @@ fn post_yaml_validation(body: String) -> std::result::Result<(String,), Validati
}
/// PostYaml - POST /post-yaml
#[tracing::instrument(skip_all)]
async fn post_yaml<I, A>(
async fn post_yaml<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -458,7 +492,8 @@ async fn post_yaml<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || post_yaml_validation(body))
@ -474,7 +509,7 @@ where
let result = api_impl
.as_ref()
.post_yaml(method, host, cookies, body)
.post_yaml(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -486,10 +521,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -505,7 +544,7 @@ fn raw_json_get_validation() -> std::result::Result<(), ValidationErrors> {
}
/// RawJsonGet - GET /raw_json
#[tracing::instrument(skip_all)]
async fn raw_json_get<I, A>(
async fn raw_json_get<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -513,7 +552,8 @@ async fn raw_json_get<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || raw_json_get_validation())
@ -527,7 +567,10 @@ where
.map_err(|_| StatusCode::BAD_REQUEST);
};
let result = api_impl.as_ref().raw_json_get(method, host, cookies).await;
let result = api_impl
.as_ref()
.raw_json_get(&method, &host, &cookies)
.await;
let mut response = Response::builder();
@ -557,10 +600,14 @@ where
response.body(Body::from(body_content))
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};
@ -587,7 +634,7 @@ fn solo_object_post_validation(
}
/// SoloObjectPost - POST /solo-object
#[tracing::instrument(skip_all)]
async fn solo_object_post<I, A>(
async fn solo_object_post<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -596,7 +643,8 @@ async fn solo_object_post<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || solo_object_post_validation(body))
@ -612,7 +660,7 @@ where
let result = api_impl
.as_ref()
.solo_object_post(method, host, cookies, body)
.solo_object_post(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -624,10 +672,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};

View File

@ -40,7 +40,7 @@ tokio = { version = "1", default-features = false, features = [
] }
tracing = { version = "0.1", features = ["attributes"] }
uuid = { version = "1", features = ["serde"] }
validator = { version = "0.19", features = ["derive"] }
validator = { version = "0.20", features = ["derive"] }
[dev-dependencies]
tracing-subscriber = "0.3"

View File

@ -12,7 +12,7 @@ server, you can easily generate a server stub.
To see how to make this your own, look here: [README]((https://openapi-generator.tech))
- API version: 0.0.1
- Generator version: 7.11.0-SNAPSHOT
- Generator version: 7.12.0-SNAPSHOT
@ -43,16 +43,18 @@ struct ServerImpl {
#[allow(unused_variables)]
#[async_trait]
impl rust-axum-validation-test::Api for ServerImpl {
impl rust_axum_validation_test::apis::default::Api for ServerImpl {
// API implementation goes here
}
impl rust_axum_validation_test::apis::ErrorHandler for ServerImpl {}
pub async fn start_server(addr: &str) {
// initialize tracing
tracing_subscriber::fmt::init();
// Init Axum router
let app = rust-axum-validation-test::server::new(Arc::new(ServerImpl));
let app = rust_axum_validation_test::server::new(Arc::new(ServerImpl));
// Add layers to the router
let app = app.layer(...);

View File

@ -18,13 +18,13 @@ pub enum MailPutResponse {
/// Default
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Default {
pub trait Default<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
/// MailPut - PUT /mail
async fn mail_put(
&self,
method: Method,
host: Host,
cookies: CookieJar,
body: models::Email,
) -> Result<MailPutResponse, ()>;
method: &Method,
host: &Host,
cookies: &CookieJar,
body: &models::Email,
) -> Result<MailPutResponse, E>;
}

View File

@ -1 +1,21 @@
pub mod default;
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {
#[allow(unused_variables)]
#[tracing::instrument(skip_all)]
async fn handle_error(
&self,
method: &::http::Method,
host: &axum::extract::Host,
cookies: &axum_extra::extract::CookieJar,
error: E,
) -> Result<axum::response::Response, http::StatusCode> {
tracing::error!("Unhandled error: {:?}", error);
axum::response::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.body(axum::body::Body::empty())
.map_err(|_| http::StatusCode::INTERNAL_SERVER_ERROR)
}
}

View File

@ -13,20 +13,21 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A>(api_impl: I) -> Router
pub fn new<I, A, E>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::default::Default + 'static,
A: apis::default::Default<E> + Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{
// build our application with a route
Router::new()
.route("/mail", put(mail_put::<I, A>))
.route("/mail", put(mail_put::<I, A, E>))
.with_state(api_impl)
}
/// MailPut - PUT /mail
#[tracing::instrument(skip_all)]
async fn mail_put<I, A>(
async fn mail_put<I, A, E>(
method: Method,
host: Host,
cookies: CookieJar,
@ -35,11 +36,12 @@ async fn mail_put<I, A>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default,
A: apis::default::Default<E> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
let result = api_impl
.as_ref()
.mail_put(method, host, cookies, body)
.mail_put(&method, &host, &cookies, &body)
.await;
let mut response = Response::builder();
@ -51,10 +53,14 @@ where
response.body(Body::empty())
}
},
Err(_) => {
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.status(500).body(Body::empty())
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
.await;
}
};