Parse If-{None-}Match headers
This commit is contained in:
parent
5d85fd16f2
commit
52d767edae
4 changed files with 30 additions and 7 deletions
|
@ -1,4 +1,4 @@
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use hyper::{Request, Response, body::Bytes};
|
use hyper::{Request, Response, body::Bytes};
|
||||||
use hyper::body::Incoming;
|
use hyper::body::Incoming;
|
||||||
use http_body_util::Full;
|
use http_body_util::Full;
|
||||||
|
@ -17,6 +17,7 @@ use http_body_util::BodyExt;
|
||||||
use aero_dav::types as dav;
|
use aero_dav::types as dav;
|
||||||
use aero_dav::xml as dxml;
|
use aero_dav::xml as dxml;
|
||||||
use super::controller::HttpResponse;
|
use super::controller::HttpResponse;
|
||||||
|
use super::node::PutPolicy;
|
||||||
|
|
||||||
pub(crate) fn depth(req: &Request<impl hyper::body::Body>) -> dav::Depth {
|
pub(crate) fn depth(req: &Request<impl hyper::body::Body>) -> dav::Depth {
|
||||||
match req.headers().get("Depth").map(hyper::header::HeaderValue::to_str) {
|
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> {
|
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 {}))
|
UnsyncBoxBody::new(Full::new(Bytes::from(txt)).map_err(|e| match e {}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,7 @@ impl Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put(self) -> Result<HttpResponse> {
|
async fn put(self) -> Result<HttpResponse> {
|
||||||
//@FIXME temporary, look at If-None-Match & If-Match headers
|
let put_policy = codec::put_policy(&self.req)?;
|
||||||
let put_policy = PutPolicy::CreateOnly;
|
|
||||||
|
|
||||||
let stream_of_frames = BodyStream::new(self.req.into_body());
|
let stream_of_frames = BodyStream::new(self.req.into_body());
|
||||||
let stream_of_bytes = stream_of_frames
|
let stream_of_bytes = stream_of_frames
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::stream::{BoxStream, Stream, StreamExt};
|
use futures::stream::{BoxStream, StreamExt};
|
||||||
use futures::future::{BoxFuture, FutureExt};
|
use futures::future::{BoxFuture, FutureExt};
|
||||||
use hyper::body::Bytes;
|
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) type PropertyStream<'a> = BoxStream<'a, std::result::Result<dav::Property<All>, dav::PropertyRequest<All>>>;
|
||||||
|
|
||||||
pub(crate) enum PutPolicy {
|
pub(crate) enum PutPolicy {
|
||||||
|
OverwriteAll,
|
||||||
CreateOnly,
|
CreateOnly,
|
||||||
ReplaceEtag(String),
|
ReplaceEtag(String),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
type ArcUser = std::sync::Arc<User>;
|
type ArcUser = std::sync::Arc<User>;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use futures::stream::{TryStream, TryStreamExt, StreamExt};
|
use futures::stream::{TryStreamExt, StreamExt};
|
||||||
use futures::io::AsyncReadExt;
|
use futures::io::AsyncReadExt;
|
||||||
use futures::{future::BoxFuture, future::FutureExt};
|
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::types as dav;
|
||||||
use aero_dav::caltypes as cal;
|
use aero_dav::caltypes as cal;
|
||||||
use aero_dav::acltypes as acl;
|
use aero_dav::acltypes as acl;
|
||||||
|
|
Loading…
Reference in a new issue