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/08/14 09:24:08 UTC
(opendal) branch main updated: feat(services/tos): support presigned URLs (#8044)
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 d2472c380 feat(services/tos): support presigned URLs (#8044)
d2472c380 is described below
commit d2472c380ec1922a8fd864e18ebc3579c86616d1
Author: Xin Sun <dd...@gmail.com>
AuthorDate: Fri Aug 14 17:24:02 2026 +0800
feat(services/tos): support presigned URLs (#8044)
feat(services/tos): add presign support
Change-Id: I8876d35e13a3d60ea1f3a32b4ff9af95aaf511a0
---
core/Cargo.lock | 4 ++--
core/services/tos/Cargo.toml | 2 +-
core/services/tos/src/backend.rs | 40 +++++++++++++++++++++++++++++++--------
core/services/tos/src/core.rs | 41 ++++++++++++++++++++++++++++++++++------
core/services/tos/src/docs.md | 2 +-
5 files changed, 71 insertions(+), 18 deletions(-)
diff --git a/core/Cargo.lock b/core/Cargo.lock
index a0c3db818..6d37d3f38 100644
--- a/core/Cargo.lock
+++ b/core/Cargo.lock
@@ -9324,9 +9324,9 @@ dependencies = [
[[package]]
name = "reqsign-volcengine-tos"
-version = "3.1.0"
+version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ac4120764e6cf8b8bd431c9256bf1defeb2331ae616d353ee9d6b750c39f62"
+checksum = "173387eb5ae4cf6a0a7098665ebcc6729862819dc3d95a81aee840767803e3d9"
dependencies = [
"anyhow",
"http 1.4.2",
diff --git a/core/services/tos/Cargo.toml b/core/services/tos/Cargo.toml
index 228c1adce..a688b3e54 100644
--- a/core/services/tos/Cargo.toml
+++ b/core/services/tos/Cargo.toml
@@ -40,6 +40,6 @@ opendal-core = { path = "../../core", version = "0.58.2", default-features = fal
quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
reqsign-core = { version = "3.2.0", default-features = false }
reqsign-file-read-tokio = { version = "3.0.3", default-features = false }
-reqsign-volcengine-tos = "3.0.3"
+reqsign-volcengine-tos = "3.1.1"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
diff --git a/core/services/tos/src/backend.rs b/core/services/tos/src/backend.rs
index 74b1c38fd..5526cee40 100644
--- a/core/services/tos/src/backend.rs
+++ b/core/services/tos/src/backend.rs
@@ -33,7 +33,7 @@ use crate::writer::TosWriter;
use http::StatusCode;
use opendal_core::OperationContext;
use opendal_core::raw::*;
-use opendal_core::{Builder, Capability, EntryMode, Error, ErrorKind, Result};
+use opendal_core::{Buffer, Builder, Capability, EntryMode, Error, ErrorKind, Result};
use reqsign_core::{Context, OsEnv, ProvideCredentialChain, Signer};
use reqsign_file_read_tokio::TokioFileRead;
use reqsign_volcengine_tos::{EnvCredentialProvider, RequestSigner, StaticCredentialProvider};
@@ -215,6 +215,12 @@ impl Builder for TosBuilder {
list_with_versions: true,
list_with_deleted: true,
+ presign: true,
+ presign_stat: true,
+ presign_read: true,
+ presign_write: true,
+ presign_delete: true,
+
stat: true,
stat_with_if_match: true,
stat_with_if_none_match: true,
@@ -416,13 +422,31 @@ impl Service for TosBackend {
async fn presign(
&self,
- _ctx: &OperationContext,
- _path: &str,
- _args: OpPresign,
+ ctx: &OperationContext,
+ path: &str,
+ args: OpPresign,
) -> Result<RpPresign> {
- Err(Error::new(
- ErrorKind::Unsupported,
- "operation is not supported",
- ))
+ let (expire, op) = args.into_parts();
+ let req = match op {
+ PresignOperation::Stat(v) => self.core.tos_head_object_request(path, v),
+ PresignOperation::Read(range, v) => self.core.tos_get_object_request(path, range, &v),
+ PresignOperation::Write(v) => {
+ self.core
+ .tos_put_object_request(path, None, &v, Buffer::new())
+ }
+ PresignOperation::Delete(v) => self.core.tos_delete_object_request(path, &v),
+ _ => Err(Error::new(
+ ErrorKind::Unsupported,
+ "operation is not supported",
+ )),
+ }?;
+ let req = self.core.sign_query(ctx, req, expire).await?;
+ let (parts, _) = req.into_parts();
+
+ Ok(RpPresign::new(PresignedRequest::new(
+ parts.method,
+ parts.uri,
+ parts.headers,
+ )))
}
}
diff --git a/core/services/tos/src/core.rs b/core/services/tos/src/core.rs
index f32066cd3..ed3436df6 100644
--- a/core/services/tos/src/core.rs
+++ b/core/services/tos/src/core.rs
@@ -16,6 +16,7 @@
// under the License.
use std::fmt::Debug;
+use std::time::Duration;
use http::Request;
use http::Response;
@@ -99,6 +100,27 @@ impl TosCore {
)
}
+ pub async fn sign_query<T>(
+ &self,
+ ctx: &OperationContext,
+ req: Request<T>,
+ duration: Duration,
+ ) -> Result<Request<T>> {
+ if self.skip_signature {
+ return Ok(req);
+ }
+
+ let (mut parts, body) = req.into_parts();
+ self.signer(ctx)
+ .sign(&mut parts, Some(duration))
+ .await
+ .map_err(|e| new_request_sign_error(e.into()))?;
+
+ parts.headers.remove(HOST);
+
+ Ok(Request::from_parts(parts, body))
+ }
+
pub async fn send(
&self,
ctx: &OperationContext,
@@ -413,12 +435,11 @@ impl TosCore {
self.send(ctx, req).await
}
- pub async fn tos_delete_object(
+ pub fn tos_delete_object_request(
&self,
- ctx: &OperationContext,
path: &str,
args: &OpDelete,
- ) -> Result<Response<Buffer>> {
+ ) -> Result<Request<Buffer>> {
let p = build_abs_path(&self.root, path);
let mut url = format!(
@@ -444,11 +465,19 @@ impl TosCore {
let req = Request::delete(&url);
- let req = req
- .extension(Operation::Delete)
+ req.extension(Operation::Delete)
.extension(ServiceOperation("DeleteObject"))
.body(Buffer::new())
- .map_err(new_request_build_error)?;
+ .map_err(new_request_build_error)
+ }
+
+ pub async fn tos_delete_object(
+ &self,
+ ctx: &OperationContext,
+ path: &str,
+ args: &OpDelete,
+ ) -> Result<Response<Buffer>> {
+ let req = self.tos_delete_object_request(path, args)?;
self.send(ctx, req).await
}
diff --git a/core/services/tos/src/docs.md b/core/services/tos/src/docs.md
index 01610d88c..6f688f1a6 100644
--- a/core/services/tos/src/docs.md
+++ b/core/services/tos/src/docs.md
@@ -10,7 +10,7 @@ Depending on its configuration and the backing system, this service can expose:
- [x] list
- [x] copy
- [ ] rename
-- [ ] presign
+- [x] presign
Inspect the effective capability set with [`opendal_core::Operator::info`] and
[`opendal_core::OperatorInfo::capability`] after building an operator.