You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/03/24 10:54:07 UTC
(opendal) branch main updated: fix(s3): Fix improper handle for copy response (#7294)
This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 22e673117 fix(s3): Fix improper handle for copy response (#7294)
22e673117 is described below
commit 22e673117ab9e92e9521fd1ca48137bd385a29d8
Author: dentiny <de...@gmail.com>
AuthorDate: Tue Mar 24 03:53:59 2026 -0700
fix(s3): Fix improper handle for copy response (#7294)
* fix(s3): Fix improper handle for copy response
* comment
* format
---
core/services/s3/src/backend.rs | 24 +++++++++++++++++++++++-
core/services/s3/src/core.rs | 11 +++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/core/services/s3/src/backend.rs b/core/services/s3/src/backend.rs
index 26d8b4713..b996cf8e9 100644
--- a/core/services/s3/src/backend.rs
+++ b/core/services/s3/src/backend.rs
@@ -1082,7 +1082,29 @@ impl Access for S3Backend {
let status = resp.status();
match status {
- StatusCode::OK => Ok(RpCopy::default()),
+ StatusCode::OK => {
+ // S3 CopyObject may return an error embedded in a 200 OK response body
+ // when the error occurs during the copy (e.g., throttling, internal error).
+ // We must parse the body to detect this.
+ //
+ // ref: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html
+ // ref: https://repost.aws/knowledge-center/s3-resolve-200-internalerror
+ let body = resp.into_body().to_bytes();
+
+ let result: CopyObjectResult =
+ quick_xml::de::from_reader(body.as_ref()).map_err(new_xml_deserialize_error)?;
+
+ // On success, ETag is always present. If it's empty, the body was not a
+ // valid <CopyObjectResult> — it's an error response embedded in 200 OK.
+ if result.etag.is_empty() {
+ return Err(
+ Error::new(ErrorKind::Unexpected, String::from_utf8_lossy(&body))
+ .set_temporary(),
+ );
+ }
+
+ Ok(RpCopy::default())
+ }
_ => Err(parse_error(resp)),
}
}
diff --git a/core/services/s3/src/core.rs b/core/services/s3/src/core.rs
index f5482754f..dbb29a5b8 100644
--- a/core/services/s3/src/core.rs
+++ b/core/services/s3/src/core.rs
@@ -1111,6 +1111,17 @@ pub struct CompleteMultipartUploadResult {
pub request_id: String,
}
+/// Partial output of a successful `CopyObject` operation.
+///
+/// ref: <https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html#API_CopyObject_ResponseSyntax>
+#[derive(Debug, Default, Deserialize)]
+#[serde(default, rename_all = "PascalCase")]
+pub struct CopyObjectResult {
+ #[serde(rename = "ETag")]
+ pub etag: String,
+ pub last_modified: String,
+}
+
/// Request of DeleteObjects.
#[derive(Default, Debug, Serialize)]
#[serde(default, rename = "Delete", rename_all = "PascalCase")]