mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 19:22:26 +00:00
Work on axum support
This commit is contained in:
120
crates/dav/src/resource/axum_service.rs
Normal file
120
crates/dav/src/resource/axum_service.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
use super::methods::{axum_route_propfind, axum_route_proppatch};
|
||||
use crate::resource::{ResourceService, axum_methods::AxumMethods};
|
||||
use axum::{
|
||||
body::Body,
|
||||
handler::Handler,
|
||||
http::{Request, Response},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use futures_util::future::BoxFuture;
|
||||
use headers::HeaderMapExt;
|
||||
use http::{HeaderValue, StatusCode};
|
||||
use std::{convert::Infallible, sync::Arc};
|
||||
use tower::Service;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AxumService<RS: ResourceService + AxumMethods> {
|
||||
resource_service: Arc<RS>,
|
||||
}
|
||||
|
||||
impl<RS: ResourceService + AxumMethods> AxumService<RS> {
|
||||
pub fn new(resource_service: Arc<RS>) -> Self {
|
||||
Self { resource_service }
|
||||
}
|
||||
}
|
||||
|
||||
impl<RS: ResourceService + AxumMethods + Clone + Send + Sync> Service<Request<Body>>
|
||||
for AxumService<RS>
|
||||
where
|
||||
RS::Error: IntoResponse + Send + Sync + 'static,
|
||||
{
|
||||
type Error = Infallible;
|
||||
type Response = Response<Body>;
|
||||
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
#[inline]
|
||||
fn poll_ready(
|
||||
&mut self,
|
||||
_cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Result<(), Self::Error>> {
|
||||
Ok(()).into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||
use crate::resource::methods::axum_route_delete;
|
||||
let mut propfind_service =
|
||||
Handler::with_state(axum_route_propfind::<RS>, self.resource_service.clone());
|
||||
let mut proppatch_service =
|
||||
Handler::with_state(axum_route_proppatch::<RS>, self.resource_service.clone());
|
||||
let mut delete_service =
|
||||
Handler::with_state(axum_route_delete::<RS>, self.resource_service.clone());
|
||||
let mut options_service = Handler::with_state(route_options::<RS>, ());
|
||||
match req.method().as_str() {
|
||||
"PROPFIND" => return Box::pin(Service::call(&mut propfind_service, req)),
|
||||
"PROPPATCH" => return Box::pin(Service::call(&mut proppatch_service, req)),
|
||||
"DELETE" => return Box::pin(Service::call(&mut delete_service, req)),
|
||||
"OPTIONS" => return Box::pin(Service::call(&mut options_service, req)),
|
||||
"REPORT" => {
|
||||
if let Some(svc) = RS::report() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"GET" => {
|
||||
if let Some(svc) = RS::get() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"HEAD" => {
|
||||
if let Some(svc) = RS::head() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"POST" => {
|
||||
if let Some(svc) = RS::post() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"MKCOL" => {
|
||||
if let Some(svc) = RS::mkcol() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"MKCALENDAR" => {
|
||||
if let Some(svc) = RS::mkcalendar() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"COPY" => {
|
||||
if let Some(svc) = RS::copy() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"MOVE" => {
|
||||
if let Some(svc) = RS::mv() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
"PUT" => {
|
||||
if let Some(svc) = RS::put() {
|
||||
return svc(self.resource_service.clone(), req);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Box::pin(async move {
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::METHOD_NOT_ALLOWED)
|
||||
.body(Body::from("Method not allowed"))
|
||||
.unwrap())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async fn route_options<RS: ResourceService + AxumMethods>() -> Response<Body> {
|
||||
let mut resp = Response::builder().status(StatusCode::OK);
|
||||
let headers = resp.headers_mut().unwrap();
|
||||
headers.insert("DAV", HeaderValue::from_static(RS::DAV_HEADER));
|
||||
headers.typed_insert(RS::allow_header());
|
||||
resp.body(Body::empty()).unwrap()
|
||||
}
|
||||
Reference in New Issue
Block a user