diff options
author | Quentin Dufour <quentin@deuxfleurs.fr> | 2024-04-24 11:43:57 +0200 |
---|---|---|
committer | Quentin Dufour <quentin@deuxfleurs.fr> | 2024-04-24 11:43:57 +0200 |
commit | 52d767edae38cc0d3effd216152ff2dcf6d19239 (patch) | |
tree | 15b32a7bdcb6f12b4c9f1dc875090a5ac7d614d7 /aero-proto/src/dav | |
parent | 5d85fd16f2625b6efb7ed70254a275237dfab1eb (diff) | |
download | aerogramme-52d767edae38cc0d3effd216152ff2dcf6d19239.tar.gz aerogramme-52d767edae38cc0d3effd216152ff2dcf6d19239.zip |
Parse If-{None-}Match headers
Diffstat (limited to 'aero-proto/src/dav')
-rw-r--r-- | aero-proto/src/dav/codec.rs | 25 | ||||
-rw-r--r-- | aero-proto/src/dav/controller.rs | 3 | ||||
-rw-r--r-- | aero-proto/src/dav/node.rs | 3 | ||||
-rw-r--r-- | aero-proto/src/dav/resource.rs | 6 |
4 files changed, 30 insertions, 7 deletions
diff --git a/aero-proto/src/dav/codec.rs b/aero-proto/src/dav/codec.rs index 9082d0a..57c3808 100644 --- a/aero-proto/src/dav/codec.rs +++ b/aero-proto/src/dav/codec.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use hyper::{Request, Response, body::Bytes}; use hyper::body::Incoming; use http_body_util::Full; @@ -17,6 +17,7 @@ use http_body_util::BodyExt; use aero_dav::types as dav; use aero_dav::xml as dxml; use super::controller::HttpResponse; +use super::node::PutPolicy; pub(crate) fn depth(req: &Request<impl hyper::body::Body>) -> dav::Depth { match req.headers().get("Depth").map(hyper::header::HeaderValue::to_str) { @@ -27,6 +28,28 @@ pub(crate) fn depth(req: &Request<impl hyper::body::Body>) -> dav::Depth { } } +pub(crate) fn put_policy(req: &Request<impl hyper::body::Body>) -> Result<PutPolicy> { + if let Some(maybe_txt_etag) = req.headers().get("If-Match").map(hyper::header::HeaderValue::to_str) { + let etag = maybe_txt_etag?; + let dquote_count = etag.chars().filter(|c| *c == '"').count(); + if dquote_count != 2 { + bail!("Either If-Match value is invalid or it's not supported (only single etag is supported)"); + } + + return Ok(PutPolicy::ReplaceEtag(etag.into())) + } + + if let Some(maybe_txt_etag) = req.headers().get("If-None-Match").map(hyper::header::HeaderValue::to_str) { + let etag = maybe_txt_etag?; + if etag == "*" { + return Ok(PutPolicy::CreateOnly) + } + bail!("Either If-None-Match value is invalid or it's not supported (only asterisk is supported)") + } + + Ok(PutPolicy::OverwriteAll) +} + pub(crate) fn text_body(txt: &'static str) -> UnsyncBoxBody<Bytes, std::io::Error> { UnsyncBoxBody::new(Full::new(Bytes::from(txt)).map_err(|e| match e {})) } diff --git a/aero-proto/src/dav/controller.rs b/aero-proto/src/dav/controller.rs index 2dcc7bc..aee86fa 100644 --- a/aero-proto/src/dav/controller.rs +++ b/aero-proto/src/dav/controller.rs @@ -180,8 +180,7 @@ impl Controller { } async fn put(self) -> Result<HttpResponse> { - //@FIXME temporary, look at If-None-Match & If-Match headers - let put_policy = PutPolicy::CreateOnly; + let put_policy = codec::put_policy(&self.req)?; let stream_of_frames = BodyStream::new(self.req.into_body()); let stream_of_bytes = stream_of_frames diff --git a/aero-proto/src/dav/node.rs b/aero-proto/src/dav/node.rs index 4d5dd1a..1ed4b0a 100644 --- a/aero-proto/src/dav/node.rs +++ b/aero-proto/src/dav/node.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use futures::stream::{BoxStream, Stream, StreamExt}; +use futures::stream::{BoxStream, StreamExt}; use futures::future::{BoxFuture, FutureExt}; use hyper::body::Bytes; @@ -13,6 +13,7 @@ pub(crate) type Content<'a> = BoxStream<'a, std::result::Result<Bytes, std::io:: pub(crate) type PropertyStream<'a> = BoxStream<'a, std::result::Result<dav::Property<All>, dav::PropertyRequest<All>>>; pub(crate) enum PutPolicy { + OverwriteAll, CreateOnly, ReplaceEtag(String), } diff --git a/aero-proto/src/dav/resource.rs b/aero-proto/src/dav/resource.rs index cb63b71..9e2ce3d 100644 --- a/aero-proto/src/dav/resource.rs +++ b/aero-proto/src/dav/resource.rs @@ -1,12 +1,12 @@ use std::sync::Arc; type ArcUser = std::sync::Arc<User>; -use anyhow::{anyhow, bail, Result}; -use futures::stream::{TryStream, TryStreamExt, StreamExt}; +use anyhow::{anyhow, Result}; +use futures::stream::{TryStreamExt, StreamExt}; use futures::io::AsyncReadExt; use futures::{future::BoxFuture, future::FutureExt}; -use aero_collections::{user::User, calendar::Calendar, davdag::{BlobId, IndexEntry, Etag}}; +use aero_collections::{user::User, calendar::Calendar, davdag::{BlobId, Etag}}; use aero_dav::types as dav; use aero_dav::caltypes as cal; use aero_dav::acltypes as acl; |