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/incubator-opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new e3fb7b00 feat(services/s3): Add if-match support (#2033)
e3fb7b00 is described below

commit e3fb7b0017f33f6112b832ad74d60a02fcd6aabf
Author: leenstx <[email protected]>
AuthorDate: Tue Apr 18 23:14:21 2023 +0800

    feat(services/s3): Add if-match support (#2033)
    
    * feat: s3: Add if-match support #1972
    
    * feat: s3: Add if-match support #1972
    
    ---------
    
    Co-authored-by: leenstx • <[email protected]>
---
 core/src/services/s3/backend.rs | 12 +++++++++---
 core/src/services/s3/core.rs    | 22 ++++++++++++++++++++--
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/core/src/services/s3/backend.rs b/core/src/services/s3/backend.rs
index c3fa6aac..da2f1181 100644
--- a/core/src/services/s3/backend.rs
+++ b/core/src/services/s3/backend.rs
@@ -944,7 +944,7 @@ impl Accessor for S3Backend {
     async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, 
Self::Reader)> {
         let resp = self
             .core
-            .s3_get_object(path, args.range(), args.if_none_match())
+            .s3_get_object(path, args.range(), args.if_none_match(), 
args.if_match())
             .await?;
 
         let status = resp.status();
@@ -967,6 +967,7 @@ impl Accessor for S3Backend {
                     args.content_type(),
                     args.content_disposition(),
                     args.cache_control(),
+                    args.if_match(),
                 )
                 .await?;
 
@@ -1017,7 +1018,10 @@ impl Accessor for S3Backend {
             return Ok(RpStat::new(Metadata::new(EntryMode::DIR)));
         }
 
-        let resp = self.core.s3_head_object(path, args.if_none_match()).await?;
+        let resp = self
+            .core
+            .s3_head_object(path, args.if_none_match(), args.if_match())
+            .await?;
 
         let status = resp.status();
 
@@ -1059,7 +1063,8 @@ impl Accessor for S3Backend {
         // We will not send this request out, just for signing.
         let mut req = match args.operation() {
             PresignOperation::Stat(v) => {
-                self.core.s3_head_object_request(path, v.if_none_match())?
+                self.core
+                    .s3_head_object_request(path, v.if_none_match(), 
v.if_match())?
             }
             PresignOperation::Read(v) => self.core.s3_get_object_request(
                 path,
@@ -1067,6 +1072,7 @@ impl Accessor for S3Backend {
                 v.override_content_disposition(),
                 v.override_cache_control(),
                 v.if_none_match(),
+                v.if_match(),
             )?,
             PresignOperation::Write(_) => {
                 self.core
diff --git a/core/src/services/s3/core.rs b/core/src/services/s3/core.rs
index b9f2281a..c618b87d 100644
--- a/core/src/services/s3/core.rs
+++ b/core/src/services/s3/core.rs
@@ -29,6 +29,7 @@ use http::header::CACHE_CONTROL;
 use http::header::CONTENT_DISPOSITION;
 use http::header::CONTENT_LENGTH;
 use http::header::CONTENT_TYPE;
+use http::header::IF_MATCH;
 use http::header::IF_NONE_MATCH;
 use http::HeaderValue;
 use http::Request;
@@ -206,6 +207,7 @@ impl S3Core {
         &self,
         path: &str,
         if_none_match: Option<&str>,
+        if_match: Option<&str>,
     ) -> Result<Request<AsyncBody>> {
         let p = build_abs_path(&self.root, path);
 
@@ -219,6 +221,10 @@ impl S3Core {
             req = req.header(IF_NONE_MATCH, if_none_match);
         }
 
+        if let Some(if_match) = if_match {
+            req = req.header(IF_MATCH, if_match);
+        }
+
         let req = req
             .body(AsyncBody::Empty)
             .map_err(new_request_build_error)?;
@@ -233,6 +239,7 @@ impl S3Core {
         override_content_disposition: Option<&str>,
         override_cache_control: Option<&str>,
         if_none_match: Option<&str>,
+        if_match: Option<&str>,
     ) -> Result<Request<AsyncBody>> {
         let p = build_abs_path(&self.root, path);
 
@@ -269,6 +276,9 @@ impl S3Core {
             req = req.header(IF_NONE_MATCH, if_none_match);
         }
 
+        if let Some(if_match) = if_match {
+            req = req.header(IF_MATCH, if_match);
+        }
         // Set SSE headers.
         // TODO: how will this work with presign?
         req = self.insert_sse_headers(req, false);
@@ -285,8 +295,10 @@ impl S3Core {
         path: &str,
         range: BytesRange,
         if_none_match: Option<&str>,
+        if_match: Option<&str>,
     ) -> Result<Response<IncomingAsyncBody>> {
-        let mut req = self.s3_get_object_request(path, range, None, None, 
if_none_match)?;
+        let mut req =
+            self.s3_get_object_request(path, range, None, None, if_none_match, 
if_match)?;
 
         self.sign(&mut req).await?;
 
@@ -342,8 +354,9 @@ impl S3Core {
         &self,
         path: &str,
         if_none_match: Option<&str>,
+        if_match: Option<&str>,
     ) -> Result<Response<IncomingAsyncBody>> {
-        let mut req = self.s3_head_object_request(path, if_none_match)?;
+        let mut req = self.s3_head_object_request(path, if_none_match, 
if_match)?;
 
         self.sign(&mut req).await?;
 
@@ -476,6 +489,7 @@ impl S3Core {
         content_type: Option<&str>,
         content_disposition: Option<&str>,
         cache_control: Option<&str>,
+        if_match: Option<&str>,
     ) -> Result<Response<IncomingAsyncBody>> {
         let p = build_abs_path(&self.root, path);
 
@@ -495,6 +509,10 @@ impl S3Core {
             req = req.header(CACHE_CONTROL, cache_control)
         }
 
+        if let Some(if_match) = if_match {
+            req = req.header(IF_MATCH, if_match)
+        }
+
         // Set storage class header
         if let Some(v) = &self.default_storage_class {
             req = 
req.header(HeaderName::from_static(constants::X_AMZ_STORAGE_CLASS), v);

Reply via email to