From 271fdfd6868980926ecc19826288e8c30ffd4935 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Wed, 31 Dec 2025 16:17:34 +0100 Subject: [PATCH] PUT object: Return ETag --- crates/caldav/src/calendar_object/methods.rs | 10 ++++++++-- crates/carddav/src/address_object/methods.rs | 9 ++++++++- crates/dav/src/resource/methods/delete.rs | 10 +++++----- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/crates/caldav/src/calendar_object/methods.rs b/crates/caldav/src/calendar_object/methods.rs index f91653c..e6fdb8a 100644 --- a/crates/caldav/src/calendar_object/methods.rs +++ b/crates/caldav/src/calendar_object/methods.rs @@ -6,7 +6,7 @@ use axum::extract::{Path, State}; use axum::response::{IntoResponse, Response}; use axum_extra::TypedHeader; use headers::{ContentType, ETag, HeaderMapExt, IfNoneMatch}; -use http::{HeaderMap, Method, StatusCode}; +use http::{HeaderMap, HeaderValue, Method, StatusCode}; use rustical_ical::CalendarObject; use rustical_store::CalendarStore; use rustical_store::auth::Principal; @@ -82,9 +82,15 @@ pub async fn put_event( debug!("invalid calendar data:\n{body}"); return Err(Error::PreconditionFailed(Precondition::ValidCalendarData)); }; + let etag = object.get_etag(); cal_store .put_object(principal, calendar_id, object, overwrite) .await?; - Ok(StatusCode::CREATED.into_response()) + let mut headers = HeaderMap::new(); + headers.insert( + "ETag", + HeaderValue::from_str(&etag).expect("Contains no invalid characters"), + ); + Ok((StatusCode::CREATED, headers).into_response()) } diff --git a/crates/carddav/src/address_object/methods.rs b/crates/carddav/src/address_object/methods.rs index 415d43c..9520189 100644 --- a/crates/carddav/src/address_object/methods.rs +++ b/crates/carddav/src/address_object/methods.rs @@ -7,6 +7,7 @@ use axum::extract::{Path, State}; use axum::response::{IntoResponse, Response}; use axum_extra::TypedHeader; use axum_extra::headers::{ContentType, ETag, HeaderMapExt, IfNoneMatch}; +use http::HeaderValue; use http::Method; use http::{HeaderMap, StatusCode}; use rustical_dav::privileges::UserPrivilege; @@ -87,9 +88,15 @@ pub async fn put_object( }; let object = AddressObject::from_vcf(object_id, body)?; + let etag = object.get_etag(); addr_store .put_object(principal, addressbook_id, object, overwrite) .await?; - Ok(StatusCode::CREATED.into_response()) + let mut headers = HeaderMap::new(); + headers.insert( + "ETag", + HeaderValue::from_str(&etag).expect("Contains no invalid characters"), + ); + Ok((StatusCode::CREATED, headers).into_response()) } diff --git a/crates/dav/src/resource/methods/delete.rs b/crates/dav/src/resource/methods/delete.rs index 2a69062..893ffbc 100644 --- a/crates/dav/src/resource/methods/delete.rs +++ b/crates/dav/src/resource/methods/delete.rs @@ -52,11 +52,11 @@ pub async fn route_delete( return Err(Error::Unauthorized.into()); } - if let Some(if_match) = if_match { - if !resource.satisfies_if_match(&if_match) { - // Precondition failed - return Err(crate::Error::PreconditionFailed.into()); - } + if let Some(if_match) = if_match + && !resource.satisfies_if_match(&if_match) + { + // Precondition failed + return Err(crate::Error::PreconditionFailed.into()); } if let Some(if_none_match) = if_none_match && resource.satisfies_if_none_match(&if_none_match)