This is an automated email from the ASF dual-hosted git repository.
erickguan 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 e489f0bc6 feat(services/http): support if_modified_since and
if_unmodified_since (#7636)
e489f0bc6 is described below
commit e489f0bc6b9ca842f8dfe5c9f3d9766163a2d0d6
Author: Yuang Gao <[email protected]>
AuthorDate: Sun Jun 28 00:08:09 2026 -0700
feat(services/http): support if_modified_since and if_unmodified_since
(#7636)
* feat(services/http): support if_modified_since and if_unmodified_since
Inject If-Modified-Since and If-Unmodified-Since in http_get_request
and http_head_request, and declare the matching read/stat capabilities.
Part of #5486.
* test(python): drop unnecessary delete capability and cleanup
---
bindings/python/tests/test_read.py | 7 ++++---
core/services/http/src/backend.rs | 4 ++++
core/services/http/src/core.rs | 18 ++++++++++++++++++
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/bindings/python/tests/test_read.py
b/bindings/python/tests/test_read.py
index f8987e1a7..002be4ae2 100644
--- a/bindings/python/tests/test_read.py
+++ b/bindings/python/tests/test_read.py
@@ -258,7 +258,10 @@ async def test_async_read_not_exists(service_name,
operator, async_operator):
@pytest.mark.need_capability(
- "read", "read_with_if_modified_since", "read_with_if_unmodified_since"
+ "read",
+ "write",
+ "read_with_if_modified_since",
+ "read_with_if_unmodified_since",
)
def test_sync_conditional_reads(service_name, operator):
path = f"random_file_{str(uuid4())}"
@@ -282,5 +285,3 @@ def test_sync_conditional_reads(service_name, operator):
# Should fail: file was modified after `before`
with pytest.raises(ConditionNotMatch):
operator.read(path, if_unmodified_since=before)
-
- operator.delete(path)
diff --git a/core/services/http/src/backend.rs
b/core/services/http/src/backend.rs
index 56ba41b62..5f44e01b9 100644
--- a/core/services/http/src/backend.rs
+++ b/core/services/http/src/backend.rs
@@ -133,12 +133,16 @@ impl Builder for HttpBuilder {
stat: true,
stat_with_if_match: true,
stat_with_if_none_match: true,
+ stat_with_if_modified_since: true,
+ stat_with_if_unmodified_since: true,
read: true,
read_with_suffix: true,
read_with_if_match: true,
read_with_if_none_match: true,
+ read_with_if_modified_since: true,
+ read_with_if_unmodified_since: true,
presign: auth.is_none(),
presign_read: auth.is_none(),
diff --git a/core/services/http/src/core.rs b/core/services/http/src/core.rs
index b8ae55657..a98a37c5f 100644
--- a/core/services/http/src/core.rs
+++ b/core/services/http/src/core.rs
@@ -21,7 +21,9 @@ use http::Request;
use http::Response;
use http::header;
use http::header::IF_MATCH;
+use http::header::IF_MODIFIED_SINCE;
use http::header::IF_NONE_MATCH;
+use http::header::IF_UNMODIFIED_SINCE;
use opendal_core::raw::*;
use opendal_core::*;
@@ -70,6 +72,14 @@ impl HttpCore {
req = req.header(IF_NONE_MATCH, if_none_match);
}
+ if let Some(if_modified_since) = args.if_modified_since() {
+ req = req.header(IF_MODIFIED_SINCE,
if_modified_since.format_http_date());
+ }
+
+ if let Some(if_unmodified_since) = args.if_unmodified_since() {
+ req = req.header(IF_UNMODIFIED_SINCE,
if_unmodified_since.format_http_date());
+ }
+
if let Some(auth) = &self.authorization {
req = req.header(header::AUTHORIZATION, auth.clone())
}
@@ -111,6 +121,14 @@ impl HttpCore {
req = req.header(IF_NONE_MATCH, if_none_match);
}
+ if let Some(if_modified_since) = args.if_modified_since() {
+ req = req.header(IF_MODIFIED_SINCE,
if_modified_since.format_http_date());
+ }
+
+ if let Some(if_unmodified_since) = args.if_unmodified_since() {
+ req = req.header(IF_UNMODIFIED_SINCE,
if_unmodified_since.format_http_date());
+ }
+
if let Some(auth) = &self.authorization {
req = req.header(header::AUTHORIZATION, auth.clone())
}