diff --git a/crates/caldav/src/error.rs b/crates/caldav/src/error.rs index 3fc5530..8ec67eb 100644 --- a/crates/caldav/src/error.rs +++ b/crates/caldav/src/error.rs @@ -23,7 +23,7 @@ impl IntoResponse for Precondition { if let Err(err) = error.serialize_root(&mut writer) { return rustical_dav::Error::from(err).into_response(); } - let mut res = Response::builder().status(StatusCode::PRECONDITION_FAILED); + let mut res = Response::builder().status(StatusCode::FORBIDDEN); res.headers_mut().unwrap().typed_insert(ContentType::xml()); res.body(Body::from(output)).unwrap() } @@ -72,7 +72,10 @@ impl Error { Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, Self::ChronoParseError(_) | Self::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, Self::NotFound => StatusCode::NOT_FOUND, - Self::PreconditionFailed(_err) => StatusCode::PRECONDITION_FAILED, + // The correct status code for a failed precondition is not PreconditionFailed but + // Forbidden (or Conflict): + // https://datatracker.ietf.org/doc/html/rfc4791#section-1.3 + Self::PreconditionFailed(_err) => StatusCode::FORBIDDEN, } } } @@ -82,10 +85,7 @@ impl IntoResponse for Error { if let Self::PreconditionFailed(precondition) = self { return precondition.into_response(); } - if matches!( - self.status_code(), - StatusCode::INTERNAL_SERVER_ERROR | StatusCode::PRECONDITION_FAILED - ) { + if matches!(self.status_code(), StatusCode::INTERNAL_SERVER_ERROR) { error!("{self}"); } (self.status_code(), self.to_string()).into_response() diff --git a/crates/dav/src/error.rs b/crates/dav/src/error.rs index 1d0e386..98dcd48 100644 --- a/crates/dav/src/error.rs +++ b/crates/dav/src/error.rs @@ -51,19 +51,18 @@ impl Error { _ => StatusCode::BAD_REQUEST, }, Self::PropReadOnly => StatusCode::CONFLICT, - Self::PreconditionFailed => StatusCode::PRECONDITION_FAILED, Self::InternalError | Self::IOError(_) => StatusCode::INTERNAL_SERVER_ERROR, - Self::Forbidden => StatusCode::FORBIDDEN, + // The correct status code for a failed precondition is not PreconditionFailed but + // Forbidden (or Conflict): + // https://datatracker.ietf.org/doc/html/rfc4791#section-1.3 + Self::PreconditionFailed | Self::Forbidden => StatusCode::FORBIDDEN, } } } impl axum::response::IntoResponse for Error { fn into_response(self) -> axum::response::Response { - if matches!( - self.status_code(), - StatusCode::INTERNAL_SERVER_ERROR | StatusCode::PRECONDITION_FAILED - ) { + if matches!(self.status_code(), StatusCode::INTERNAL_SERVER_ERROR) { error!("{self}"); } diff --git a/crates/store/src/error.rs b/crates/store/src/error.rs index 259a9fa..d20dc06 100644 --- a/crates/store/src/error.rs +++ b/crates/store/src/error.rs @@ -53,9 +53,7 @@ impl IntoResponse for Error { fn into_response(self) -> axum::response::Response { if matches!( self.status_code(), - StatusCode::INTERNAL_SERVER_ERROR - | StatusCode::PRECONDITION_FAILED - | StatusCode::CONFLICT + StatusCode::INTERNAL_SERVER_ERROR | StatusCode::CONFLICT ) { error!("{self}"); } diff --git a/src/integration_tests/caldav/calendar_put.rs b/src/integration_tests/caldav/calendar_put.rs index b99f274..ba4b818 100644 --- a/src/integration_tests/caldav/calendar_put.rs +++ b/src/integration_tests/caldav/calendar_put.rs @@ -66,7 +66,7 @@ END:VCALENDAR"; .typed_insert(Authorization::basic("user", "pass")); let response = app.clone().oneshot(request).await.unwrap(); - assert_eq!(response.status(), StatusCode::PRECONDITION_FAILED); + assert_eq!(response.status(), StatusCode::FORBIDDEN); let body = response.extract_string().await; insta::assert_snapshot!(body, @r#"