[Rust-Axum] Implement support for Basic and Bearer auth in Claims (#20584)

* 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

* Rebase error handler

* Rebase with updated error handler

* Update deps

* Fix capture group syntax

* Rebase rust-axum-error-handling

* Update docs

* Multipart is also part of the axum update

* Update samples

* Update docs
This commit is contained in:
Victoria Casasampere Fernandez 2025-02-19 07:48:28 +01:00 committed by GitHub
parent eb668b6a76
commit d5866feb2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 267 additions and 207 deletions

View File

@ -209,16 +209,16 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Union|✗|OAS3
|allOf|✗|OAS2,OAS3
|anyOf|✗|OAS3
|oneOf||OAS3
|oneOf||OAS3
|not|✗|OAS3
### Security Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasicAuth||OAS2,OAS3
|BasicAuth||OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect|✗|OAS3
|BearerToken||OAS3
|BearerToken||OAS3
|OAuth2_Implicit|✗|OAS2,OAS3
|OAuth2_Password|✗|OAS2,OAS3
|OAuth2_ClientCredentials|✗|OAS2,OAS3

View File

@ -85,6 +85,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
// Grouping (Method, Operation) by Path.
private final Map<String, ArrayList<MethodOperation>> pathMethodOpMap = new HashMap<>();
private boolean havingAuthMethods = false;
private boolean havingBasicAuthMethods = false;
// Logger
private final Logger LOGGER = LoggerFactory.getLogger(RustAxumServerCodegen.class);
@ -98,7 +99,14 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
WireFormatFeature.Custom
))
.securityFeatures(EnumSet.of(
SecurityFeature.ApiKey
SecurityFeature.ApiKey,
SecurityFeature.BasicAuth,
SecurityFeature.BearerToken
))
.schemaSupportFeatures(EnumSet.of(
SchemaSupportFeature.Simple,
SchemaSupportFeature.Composite,
SchemaSupportFeature.oneOf
))
.excludeGlobalFeatures(
GlobalFeature.Info,
@ -777,6 +785,16 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
op.vendorExtensions.put("x-has-auth-methods", true);
hasAuthMethod = true;
} else if (s.isBasic) {
op.vendorExtensions.put("x-has-basic-auth-methods", true);
op.vendorExtensions.put("x-is-basic-bearer", s.isBasicBearer);
op.vendorExtensions.put("x-api-auth-header-name", "authorization");
op.vendorExtensions.put("x-has-auth-methods", true);
hasAuthMethod = true;
if (!this.havingBasicAuthMethods)
this.havingBasicAuthMethods = true;
}
}
}
@ -878,6 +896,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
.collect(Collectors.toList());
bundle.put("pathMethodOps", pathMethodOps);
if (havingAuthMethods) bundle.put("havingAuthMethods", true);
if (havingBasicAuthMethods) bundle.put("havingBasicAuthMethods", true);
return super.postProcessSupportingFileData(bundle);
}

View File

@ -12,9 +12,10 @@ pub mod {{classFilename}};
pub trait CookieAuthentication {
type Claims;
/// Extracting Claims from Cookie. Return None if the Claims is invalid.
/// Extracting Claims from Cookie. Return None if the Claims are invalid.
async fn extract_claims_from_cookie(&self, cookies: &axum_extra::extract::CookieJar, key: &str) -> Option<Self::Claims>;
}
{{/isKeyInCookie}}
{{#isKeyInHeader}}
/// API Key Authentication - Header.
@ -22,12 +23,32 @@ pub trait CookieAuthentication {
pub trait ApiKeyAuthHeader {
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_header(&self, headers: &axum::http::header::HeaderMap, key: &str) -> Option<Self::Claims>;
}
{{/isKeyInHeader}}
{{/isApiKey}}
{{/authMethods}}
{{#havingBasicAuthMethods}}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BasicAuthKind {
Basic,
Bearer,
}
/// API Key Authentication - Authentication Header.
/// For `Basic token` and `Bearer token`
#[async_trait::async_trait]
pub trait ApiAuthBasic {
type Claims;
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_auth_header(&self, kind: BasicAuthKind, headers: &axum::http::header::HeaderMap, key: &str) -> Option<Self::Claims>;
}
{{/havingBasicAuthMethods}}
// Error handler for unhandled errors.
#[async_trait::async_trait]

View File

@ -12,6 +12,11 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A, E{
{{#x-has-header-auth-methods}}
headers: HeaderMap,
{{/x-has-header-auth-methods}}
{{^x-has-header-auth-methods}}
{{#x-has-basic-auth-methods}}
headers: HeaderMap,
{{/x-has-basic-auth-methods}}
{{/x-has-header-auth-methods}}
{{/vendorExtensions}}
{{/headerParams.size}}
{{#pathParams.size}}
@ -54,7 +59,7 @@ async fn {{#vendorExtensions}}{{{x-operation-id}}}{{/vendorExtensions}}<I, A, E{
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
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,
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}}{{#x-has-basic-auth-methods}}+ apis::ApiAuthBasic<Claims = C>{{/x-has-basic-auth-methods}}{{/vendorExtensions}} + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
{{#vendorExtensions}}
@ -67,6 +72,9 @@ where
{{#x-has-header-auth-methods}}
let claims_in_header = api_impl.as_ref().extract_claims_from_header(&headers, "{{x-api-key-header-name}}").await;
{{/x-has-header-auth-methods}}
{{#x-has-basic-auth-methods}}
let claims_in_auth_header = api_impl.as_ref().extract_claims_from_auth_header(apis::BasicAuthKind::{{#x-is-basic-bearer}}Bearer{{/x-is-basic-bearer}}{{^x-is-basic-bearer}}Basic{{/x-is-basic-bearer}}, &headers, "{{x-api-auth-header-name}}").await;
{{/x-has-basic-auth-methods}}
{{#x-has-auth-methods}}
let claims = None
{{#x-has-cookie-auth-methods}}
@ -75,6 +83,9 @@ where
{{#x-has-header-auth-methods}}
.or(claims_in_header)
{{/x-has-header-auth-methods}}
{{#x-has-basic-auth-methods}}
.or(claims_in_auth_header)
{{/x-has-basic-auth-methods}}
;
let Some(claims) = claims else {
return Response::builder()
@ -346,7 +357,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
},
};

View File

@ -2,7 +2,7 @@
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}}<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,
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}}{{#isBasic}}apis::ApiAuthBasic<Claims = C> + {{/isBasic}}{{/authMethods}}Send + Sync + 'static,
E: std::fmt::Debug + Send + Sync + 'static,
{{#havingAuthMethods}}C: Send + Sync + 'static,{{/havingAuthMethods}}
{

View File

@ -5,19 +5,20 @@ pub mod payments;
pub trait ApiKeyAuthHeader {
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_header(
&self,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<Self::Claims>;
}
/// Cookie Authentication.
#[async_trait::async_trait]
pub trait CookieAuthentication {
type Claims;
/// Extracting Claims from Cookie. Return None if the Claims is invalid.
/// Extracting Claims from Cookie. Return None if the Claims are invalid.
async fn extract_claims_from_cookie(
&self,
cookies: &axum_extra::extract::CookieJar,
@ -25,6 +26,28 @@ pub trait CookieAuthentication {
) -> Option<Self::Claims>;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BasicAuthKind {
Basic,
Bearer,
}
/// API Key Authentication - Authentication Header.
/// For `Basic token` and `Bearer token`
#[async_trait::async_trait]
pub trait ApiAuthBasic {
type Claims;
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_auth_header(
&self,
kind: BasicAuthKind,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<Self::Claims>;
}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {

View File

@ -51,6 +51,7 @@ pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
path_params: &models::GetPaymentMethodByIdPathParams,
) -> Result<GetPaymentMethodByIdResponse, E>;
@ -62,6 +63,7 @@ pub trait Payments<E: std::fmt::Debug + Send + Sync + 'static = ()>:
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
) -> Result<GetPaymentMethodsResponse, E>;
/// Make a payment.

View File

@ -17,6 +17,8 @@ pub fn new<I, A, E, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::payments::Payments<E, Claims = C>
+ apis::ApiAuthBasic<Claims = C>
+ apis::ApiAuthBasic<Claims = C>
+ apis::ApiKeyAuthHeader<Claims = C>
+ apis::CookieAuthentication<Claims = C>
+ Send
@ -53,14 +55,28 @@ async fn get_payment_method_by_id<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
headers: HeaderMap,
Path(path_params): Path<models::GetPaymentMethodByIdPathParams>,
State(api_impl): State<I>,
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments<E, Claims = C> + Send + Sync,
A: apis::payments::Payments<E, Claims = C> + apis::ApiAuthBasic<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_auth_header = api_impl
.as_ref()
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
.await;
let claims = None.or(claims_in_auth_header);
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
};
#[allow(clippy::redundant_closure)]
let validation =
tokio::task::spawn_blocking(move || get_payment_method_by_id_validation(path_params))
@ -76,7 +92,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, &claims, &path_params)
.await;
let mut response = Response::builder();
@ -133,7 +149,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -157,13 +172,27 @@ async fn get_payment_methods<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
headers: HeaderMap,
State(api_impl): State<I>,
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments<E, Claims = C> + Send + Sync,
A: apis::payments::Payments<E, Claims = C> + apis::ApiAuthBasic<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_auth_header = api_impl
.as_ref()
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
.await;
let claims = None.or(claims_in_auth_header);
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || get_payment_methods_validation())
.await
@ -178,7 +207,7 @@ where
let result = api_impl
.as_ref()
.get_payment_methods(&method, &host, &cookies)
.get_payment_methods(&method, &host, &cookies, &claims)
.await;
let mut response = Response::builder();
@ -212,7 +241,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -250,6 +278,7 @@ async fn post_make_payment<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
headers: HeaderMap,
State(api_impl): State<I>,
Json(body): Json<Option<models::Payment>>,
) -> Result<Response, StatusCode>
@ -257,6 +286,7 @@ where
I: AsRef<A> + Send + Sync,
A: apis::payments::Payments<E, Claims = C>
+ apis::CookieAuthentication<Claims = C>
+ apis::ApiAuthBasic<Claims = C>
+ Send
+ Sync,
E: std::fmt::Debug + Send + Sync + 'static,
@ -266,7 +296,11 @@ where
.as_ref()
.extract_claims_from_cookie(&cookies, "X-API-Key")
.await;
let claims = None.or(claims_in_cookie);
let claims_in_auth_header = api_impl
.as_ref()
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
.await;
let claims = None.or(claims_in_cookie).or(claims_in_auth_header);
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
@ -345,7 +379,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -84,7 +84,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -145,7 +144,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -207,7 +205,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -226,7 +226,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -288,7 +287,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -350,7 +348,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -412,7 +409,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -482,7 +478,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -544,7 +539,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -606,7 +600,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -701,7 +694,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -777,7 +769,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -970,7 +961,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1028,7 +1018,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
},
};
@ -1106,7 +1095,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
},
};
@ -1176,7 +1164,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1233,7 +1220,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1314,7 +1300,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1372,7 +1357,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
},
};
@ -1431,7 +1415,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1497,7 +1480,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1662,7 +1644,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1777,7 +1758,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1882,7 +1862,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1955,7 +1934,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl.as_ref().handle_error(&method, &host, &cookies, why).await;
},
};
@ -2025,7 +2003,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2093,7 +2070,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2173,7 +2149,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2241,7 +2216,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2309,7 +2283,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2377,7 +2350,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2458,7 +2430,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2528,7 +2499,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -104,7 +104,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -161,7 +160,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -218,7 +216,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -275,7 +272,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -332,7 +328,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -389,7 +384,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -446,7 +440,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -503,7 +496,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -560,7 +552,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -617,7 +608,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -674,7 +664,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -731,7 +720,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -788,7 +776,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -845,7 +832,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -902,7 +888,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -959,7 +944,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1016,7 +1000,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1073,7 +1056,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1130,7 +1112,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1187,7 +1168,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1244,7 +1224,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1301,7 +1280,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1358,7 +1336,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1415,7 +1392,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1472,7 +1448,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1529,7 +1504,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1586,7 +1560,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1643,7 +1616,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1700,7 +1672,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1757,7 +1728,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1814,7 +1784,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1871,7 +1840,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1928,7 +1896,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1985,7 +1952,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2042,7 +2008,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2099,7 +2064,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2156,7 +2120,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -119,6 +119,8 @@ pub enum TestJsonFormDataResponse {
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHandler<E> {
type Claims;
/// Call123example - GET /v2/fake/operation-with-numeric-id
async fn call123example(
&self,
@ -209,6 +211,7 @@ pub trait Fake<E: std::fmt::Debug + Send + Sync + 'static = ()>: super::ErrorHan
method: &Method,
host: &Host,
cookies: &CookieJar,
claims: &Self::Claims,
body: &models::TestEndpointParametersRequest,
) -> Result<TestEndpointParametersResponse, E>;

View File

@ -10,7 +10,7 @@ pub mod user;
pub trait ApiKeyAuthHeader {
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_header(
&self,
headers: &axum::http::header::HeaderMap,
@ -18,6 +18,28 @@ pub trait ApiKeyAuthHeader {
) -> Option<Self::Claims>;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BasicAuthKind {
Basic,
Bearer,
}
/// API Key Authentication - Authentication Header.
/// For `Basic token` and `Bearer token`
#[async_trait::async_trait]
pub trait ApiAuthBasic {
type Claims;
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_auth_header(
&self,
kind: BasicAuthKind,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<Self::Claims>;
}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {

View File

@ -17,12 +17,13 @@ pub fn new<I, A, E, C>(api_impl: I) -> Router
where
I: AsRef<A> + Clone + Send + Sync + 'static,
A: apis::another_fake::AnotherFake<E>
+ apis::fake::Fake<E>
+ apis::fake::Fake<E, Claims = C>
+ apis::fake_classname_tags123::FakeClassnameTags123<E>
+ apis::pet::Pet<E, Claims = C>
+ apis::store::Store<E, Claims = C>
+ apis::user::User<E>
+ apis::ApiKeyAuthHeader<Claims = C>
+ apis::ApiAuthBasic<Claims = C>
+ Send
+ Sync
+ 'static,
@ -37,46 +38,49 @@ where
)
.route(
"/v2/fake",
get(test_enum_parameters::<I, A, E>)
.patch(test_client_model::<I, A, E>)
.post(test_endpoint_parameters::<I, A, E>),
get(test_enum_parameters::<I, A, E, C>)
.patch(test_client_model::<I, A, E, C>)
.post(test_endpoint_parameters::<I, A, E, C>),
)
.route(
"/v2/fake/body-with-query-params",
put(test_body_with_query_params::<I, A, E>),
put(test_body_with_query_params::<I, A, E, C>),
)
.route(
"/v2/fake/hyphenParam/{hyphen_param}",
get(hyphen_param::<I, A, E>),
get(hyphen_param::<I, A, E, C>),
)
.route(
"/v2/fake/inline-additionalProperties",
post(test_inline_additional_properties::<I, A, E>),
post(test_inline_additional_properties::<I, A, E, C>),
)
.route(
"/v2/fake/jsonFormData",
get(test_json_form_data::<I, A, E, C>),
)
.route("/v2/fake/jsonFormData", get(test_json_form_data::<I, A, E>))
.route(
"/v2/fake/operation-with-numeric-id",
get(call123example::<I, A, E>),
get(call123example::<I, A, E, C>),
)
.route(
"/v2/fake/outer/boolean",
post(fake_outer_boolean_serialize::<I, A, E>),
post(fake_outer_boolean_serialize::<I, A, E, C>),
)
.route(
"/v2/fake/outer/composite",
post(fake_outer_composite_serialize::<I, A, E>),
post(fake_outer_composite_serialize::<I, A, E, C>),
)
.route(
"/v2/fake/outer/number",
post(fake_outer_number_serialize::<I, A, E>),
post(fake_outer_number_serialize::<I, A, E, C>),
)
.route(
"/v2/fake/outer/string",
post(fake_outer_string_serialize::<I, A, E>),
post(fake_outer_string_serialize::<I, A, E, C>),
)
.route(
"/v2/fake/response-with-numerical-description",
get(fake_response_with_numerical_description::<I, A, E>),
get(fake_response_with_numerical_description::<I, A, E, C>),
)
.route("/v2/fake_classname_test", patch(test_classname::<I, A, E>))
.route(
@ -202,7 +206,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -222,7 +225,7 @@ fn call123example_validation() -> std::result::Result<(), ValidationErrors> {
}
/// Call123example - GET /v2/fake/operation-with-numeric-id
#[tracing::instrument(skip_all)]
async fn call123example<I, A, E>(
async fn call123example<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -230,7 +233,7 @@ async fn call123example<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -262,7 +265,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -296,7 +298,7 @@ fn fake_outer_boolean_serialize_validation(
}
/// FakeOuterBooleanSerialize - POST /v2/fake/outer/boolean
#[tracing::instrument(skip_all)]
async fn fake_outer_boolean_serialize<I, A, E>(
async fn fake_outer_boolean_serialize<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -305,7 +307,7 @@ async fn fake_outer_boolean_serialize<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -357,7 +359,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -391,7 +392,7 @@ fn fake_outer_composite_serialize_validation(
}
/// FakeOuterCompositeSerialize - POST /v2/fake/outer/composite
#[tracing::instrument(skip_all)]
async fn fake_outer_composite_serialize<I, A, E>(
async fn fake_outer_composite_serialize<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -400,7 +401,7 @@ async fn fake_outer_composite_serialize<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -452,7 +453,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -486,7 +486,7 @@ fn fake_outer_number_serialize_validation(
}
/// FakeOuterNumberSerialize - POST /v2/fake/outer/number
#[tracing::instrument(skip_all)]
async fn fake_outer_number_serialize<I, A, E>(
async fn fake_outer_number_serialize<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -495,7 +495,7 @@ async fn fake_outer_number_serialize<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -547,7 +547,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -581,7 +580,7 @@ fn fake_outer_string_serialize_validation(
}
/// FakeOuterStringSerialize - POST /v2/fake/outer/string
#[tracing::instrument(skip_all)]
async fn fake_outer_string_serialize<I, A, E>(
async fn fake_outer_string_serialize<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -590,7 +589,7 @@ async fn fake_outer_string_serialize<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -642,7 +641,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -663,7 +661,7 @@ fn fake_response_with_numerical_description_validation() -> std::result::Result<
}
/// FakeResponseWithNumericalDescription - GET /v2/fake/response-with-numerical-description
#[tracing::instrument(skip_all)]
async fn fake_response_with_numerical_description<I, A, E>(
async fn fake_response_with_numerical_description<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -671,7 +669,7 @@ async fn fake_response_with_numerical_description<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -704,7 +702,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -728,7 +725,7 @@ fn hyphen_param_validation(
}
/// HyphenParam - GET /v2/fake/hyphenParam/{hyphen-param}
#[tracing::instrument(skip_all)]
async fn hyphen_param<I, A, E>(
async fn hyphen_param<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -737,7 +734,7 @@ async fn hyphen_param<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -769,7 +766,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -804,7 +800,7 @@ fn test_body_with_query_params_validation(
}
/// TestBodyWithQueryParams - PUT /v2/fake/body-with-query-params
#[tracing::instrument(skip_all)]
async fn test_body_with_query_params<I, A, E>(
async fn test_body_with_query_params<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -814,7 +810,7 @@ async fn test_body_with_query_params<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -848,7 +844,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -880,7 +875,7 @@ fn test_client_model_validation(
}
/// TestClientModel - PATCH /v2/fake
#[tracing::instrument(skip_all)]
async fn test_client_model<I, A, E>(
async fn test_client_model<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -889,7 +884,7 @@ async fn test_client_model<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -940,7 +935,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -972,18 +966,32 @@ fn test_endpoint_parameters_validation(
}
/// TestEndpointParameters - POST /v2/fake
#[tracing::instrument(skip_all)]
async fn test_endpoint_parameters<I, A, E>(
async fn test_endpoint_parameters<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
headers: HeaderMap,
State(api_impl): State<I>,
Form(body): Form<models::TestEndpointParametersRequest>,
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + apis::ApiAuthBasic<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_auth_header = api_impl
.as_ref()
.extract_claims_from_auth_header(apis::BasicAuthKind::Basic, &headers, "authorization")
.await;
let claims = None.or(claims_in_auth_header);
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || test_endpoint_parameters_validation(body))
.await
@ -998,7 +1006,7 @@ where
let result = api_impl
.as_ref()
.test_endpoint_parameters(&method, &host, &cookies, &body)
.test_endpoint_parameters(&method, &host, &cookies, &claims, &body)
.await;
let mut response = Response::builder();
@ -1017,7 +1025,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1062,7 +1069,7 @@ fn test_enum_parameters_validation(
}
/// TestEnumParameters - GET /v2/fake
#[tracing::instrument(skip_all)]
async fn test_enum_parameters<I, A, E>(
async fn test_enum_parameters<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1073,7 +1080,7 @@ async fn test_enum_parameters<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Header parameters
@ -1168,7 +1175,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1199,7 +1205,7 @@ fn test_inline_additional_properties_validation(
}
/// TestInlineAdditionalProperties - POST /v2/fake/inline-additionalProperties
#[tracing::instrument(skip_all)]
async fn test_inline_additional_properties<I, A, E>(
async fn test_inline_additional_properties<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1208,7 +1214,7 @@ async fn test_inline_additional_properties<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -1241,7 +1247,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1273,7 +1278,7 @@ fn test_json_form_data_validation(
}
/// TestJsonFormData - GET /v2/fake/jsonFormData
#[tracing::instrument(skip_all)]
async fn test_json_form_data<I, A, E>(
async fn test_json_form_data<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
@ -1282,7 +1287,7 @@ async fn test_json_form_data<I, A, E>(
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::fake::Fake<E> + Send + Sync,
A: apis::fake::Fake<E, Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
#[allow(clippy::redundant_closure)]
@ -1314,7 +1319,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1408,7 +1412,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1479,7 +1482,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1576,7 +1578,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1658,7 +1659,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1740,7 +1740,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1839,7 +1838,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1920,7 +1918,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2005,7 +2002,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2090,7 +2086,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2159,7 +2154,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2252,7 +2246,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2337,7 +2330,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2426,7 +2418,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2499,7 +2490,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2573,7 +2563,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2647,7 +2636,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2716,7 +2704,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2801,7 +2788,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2919,7 +2905,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -2979,7 +2964,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -3059,7 +3043,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -7,7 +7,7 @@ pub mod user;
pub trait ApiKeyAuthHeader {
type Claims;
/// Extracting Claims from Header. Return None if the Claims is invalid.
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_header(
&self,
headers: &axum::http::header::HeaderMap,

View File

@ -146,7 +146,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -243,7 +242,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -325,7 +323,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -407,7 +404,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -506,7 +502,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -603,7 +598,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -688,7 +682,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -773,7 +766,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -842,7 +834,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -935,7 +926,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1020,7 +1010,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1109,7 +1098,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1196,7 +1184,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1284,7 +1271,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1372,7 +1358,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1455,7 +1440,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1540,7 +1524,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1674,7 +1657,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1748,7 +1730,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -1842,7 +1823,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

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

View File

@ -1,5 +1,27 @@
pub mod default;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum BasicAuthKind {
Basic,
Bearer,
}
/// API Key Authentication - Authentication Header.
/// For `Basic token` and `Bearer token`
#[async_trait::async_trait]
pub trait ApiAuthBasic {
type Claims;
/// Extracting Claims from Header. Return None if the Claims are invalid.
async fn extract_claims_from_auth_header(
&self,
kind: BasicAuthKind,
headers: &axum::http::header::HeaderMap,
key: &str,
) -> Option<Self::Claims>;
}
// Error handler for unhandled errors.
#[async_trait::async_trait]
pub trait ErrorHandler<E: std::fmt::Debug + Send + Sync + 'static = ()> {

View File

@ -13,15 +13,20 @@ use crate::{header, types::*};
use crate::{apis, models};
/// Setup API Server.
pub fn new<I, A, E>(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::default::Default<E> + Send + Sync + 'static,
A: apis::default::Default<E, Claims = C>
+ apis::ApiAuthBasic<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("/ping", get(ping_get::<I, A, E>))
.route("/ping", get(ping_get::<I, A, E, C>))
.with_state(api_impl)
}
@ -31,17 +36,31 @@ fn ping_get_validation() -> std::result::Result<(), ValidationErrors> {
}
/// PingGet - GET /ping
#[tracing::instrument(skip_all)]
async fn ping_get<I, A, E>(
async fn ping_get<I, A, E, C>(
method: Method,
host: Host,
cookies: CookieJar,
headers: HeaderMap,
State(api_impl): State<I>,
) -> Result<Response, StatusCode>
where
I: AsRef<A> + Send + Sync,
A: apis::default::Default<E> + Send + Sync,
A: apis::default::Default<E, Claims = C> + apis::ApiAuthBasic<Claims = C> + Send + Sync,
E: std::fmt::Debug + Send + Sync + 'static,
{
// Authentication
let claims_in_auth_header = api_impl
.as_ref()
.extract_claims_from_auth_header(apis::BasicAuthKind::Bearer, &headers, "authorization")
.await;
let claims = None.or(claims_in_auth_header);
let Some(claims) = claims else {
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
};
#[allow(clippy::redundant_closure)]
let validation = tokio::task::spawn_blocking(move || ping_get_validation())
.await
@ -54,7 +73,10 @@ 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, &claims)
.await;
let mut response = Response::builder();
@ -68,7 +90,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -128,7 +128,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -100,7 +100,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -97,7 +97,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -154,7 +153,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -227,7 +225,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -306,7 +303,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -378,7 +374,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -457,7 +452,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -524,7 +518,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -603,7 +596,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)
@ -675,7 +667,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)

View File

@ -56,7 +56,6 @@ where
Err(why) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
return api_impl
.as_ref()
.handle_error(&method, &host, &cookies, why)