use axum::extract::rejection::PathRejection;
use axum_extra::routing::SecondElementIs;
use http::request::Parts;
use schemars::JsonSchema;
use serde::de::DeserializeOwned;
use super::*;
use crate::operation::{add_parameters, parameters_from_schema, OperationHandler, ParamLocation};
impl<S> crate::axum::ApiRouter<S>
where
S: Clone + Send + Sync + 'static,
{
pub fn typed_get<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::get(handler))
}
pub fn typed_get_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(P::PATH, crate::axum::routing::get_with(handler, transform))
}
pub fn typed_delete<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::delete(handler))
}
pub fn typed_delete_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(
P::PATH,
crate::axum::routing::delete_with(handler, transform),
)
}
pub fn typed_head<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::head(handler))
}
pub fn typed_head_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(P::PATH, crate::axum::routing::head_with(handler, transform))
}
pub fn typed_options<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::options(handler))
}
pub fn typed_options_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(
P::PATH,
crate::axum::routing::options_with(handler, transform),
)
}
pub fn typed_patch<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::patch(handler))
}
pub fn typed_patch_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(
P::PATH,
crate::axum::routing::patch_with(handler, transform),
)
}
pub fn typed_post<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::post(handler))
}
pub fn typed_post_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(P::PATH, crate::axum::routing::post_with(handler, transform))
}
pub fn typed_put<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::put(handler))
}
pub fn typed_put_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(P::PATH, crate::axum::routing::put_with(handler, transform))
}
pub fn typed_trace<H, I, O, T, P>(self, handler: H) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
{
self.api_route(P::PATH, crate::axum::routing::trace(handler))
}
pub fn typed_trace_with<H, I, O, T, P, F>(self, handler: H, transform: F) -> Self
where
H: axum::handler::Handler<T, S> + OperationHandler<I, O>,
T: SecondElementIs<P> + 'static,
I: OperationInput,
O: OperationOutput,
P: axum_extra::routing::TypedPath + schemars::JsonSchema + OperationInput,
F: FnOnce(TransformOperation<'_>) -> TransformOperation<'_>,
{
self.api_route(
P::PATH,
crate::axum::routing::trace_with(handler, transform),
)
}
}
#[derive(Debug)]
pub struct TypedPath<T: axum_extra::routing::TypedPath + JsonSchema>(pub T);
impl<T> OperationInput for TypedPath<T>
where
T: axum_extra::routing::TypedPath + JsonSchema,
{
fn operation_input(ctx: &mut crate::generate::GenContext, operation: &mut Operation) {
let schema = ctx.schema.root_schema_for::<T>();
operation.description = schema
.get("description")
.and_then(|d| d.as_str())
.map(String::from);
let params = parameters_from_schema(ctx, schema, ParamLocation::Path);
add_parameters(ctx, operation, params);
}
}
impl<T, S> axum::extract::FromRequestParts<S> for TypedPath<T>
where
T: DeserializeOwned + Send + axum_extra::routing::TypedPath + JsonSchema,
S: Send + Sync,
{
type Rejection = PathRejection;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let path = axum::extract::Path::<T>::from_request_parts(parts, state).await?;
Ok(Self(path.0))
}
}
impl<T, S> axum::extract::OptionalFromRequestParts<S> for TypedPath<T>
where
T: DeserializeOwned + Send + 'static + axum_extra::routing::TypedPath + JsonSchema,
S: Send + Sync,
{
type Rejection = PathRejection;
async fn from_request_parts(
parts: &mut Parts,
state: &S,
) -> Result<Option<Self>, Self::Rejection> {
let path = axum::extract::Path::<T>::from_request_parts(parts, state).await?;
Ok(path.map(|x| Self(x.0)))
}
}