This is an automated email from the ASF dual-hosted git repository.
suyanhanx 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 239d3ed3 feat(core): add presign support for obs (#2253)
239d3ed3 is described below
commit 239d3ed3548500943efc614498a51d1ff9aa75e6
Author: Will Li <[email protected]>
AuthorDate: Tue May 16 11:52:40 2023 +0800
feat(core): add presign support for obs (#2253)
* add presign support for obs
* update based on comment
---
core/src/services/obs/backend.rs | 41 ++++++++++++++++++++++++++++--
core/src/services/obs/core.rs | 54 +++++++++++++++++++++++++++++++++-------
2 files changed, 84 insertions(+), 11 deletions(-)
diff --git a/core/src/services/obs/backend.rs b/core/src/services/obs/backend.rs
index 29a745ca..1ffa052e 100644
--- a/core/src/services/obs/backend.rs
+++ b/core/src/services/obs/backend.rs
@@ -50,7 +50,7 @@ use crate::*;
/// - [ ] rename
/// - [x] list
/// - [x] scan
-/// - [ ] presign
+/// - [x] presign
/// - [ ] blocking
///
/// # Configuration
@@ -332,12 +332,49 @@ impl Accessor for ObsBackend {
list_with_delimiter_slash: true,
list_without_delimiter: true,
+ presign: true,
+ presign_stat: true,
+ presign_read: true,
+ presign_write: true,
+
..Default::default()
});
am
}
+ async fn presign(&self, path: &str, args: OpPresign) -> Result<RpPresign> {
+ let mut req = match args.operation() {
+ PresignOperation::Stat(v) => {
+ self.core
+ .obs_head_object_request(path, v.if_match(),
v.if_none_match())?
+ }
+ PresignOperation::Read(v) => self.core.obs_get_object_request(
+ path,
+ v.range(),
+ v.if_match(),
+ v.if_none_match(),
+ )?,
+ PresignOperation::Write(v) => self.core.obs_put_object_request(
+ path,
+ None,
+ v.content_type(),
+ v.cache_control(),
+ AsyncBody::Empty,
+ )?,
+ };
+ self.core.sign_query(&mut req, args.expire()).await?;
+
+ // We don't need this request anymore, consume it directly.
+ let (parts, _) = req.into_parts();
+
+ Ok(RpPresign::new(PresignedRequest::new(
+ parts.method,
+ parts.uri,
+ parts.headers,
+ )))
+ }
+
async fn create_dir(&self, path: &str, _: OpCreateDir) ->
Result<RpCreateDir> {
let mut req =
self.core
@@ -411,7 +448,7 @@ impl Accessor for ObsBackend {
let resp = self
.core
- .obs_get_head_object(path, args.if_match(), args.if_none_match())
+ .obs_head_object(path, args.if_match(), args.if_none_match())
.await?;
let status = resp.status();
diff --git a/core/src/services/obs/core.rs b/core/src/services/obs/core.rs
index 2dab3a8b..32491c59 100644
--- a/core/src/services/obs/core.rs
+++ b/core/src/services/obs/core.rs
@@ -17,6 +17,7 @@
use std::fmt::Debug;
use std::fmt::Formatter;
+use std::time::Duration;
use http::header::CACHE_CONTROL;
use http::header::CONTENT_LENGTH;
@@ -77,6 +78,18 @@ impl ObsCore {
self.signer.sign(req, &cred).map_err(new_request_sign_error)
}
+ pub async fn sign_query<T>(&self, req: &mut Request<T>, duration:
Duration) -> Result<()> {
+ let cred = if let Some(cred) = self.load_credential().await? {
+ cred
+ } else {
+ return Ok(());
+ };
+
+ self.signer
+ .sign_query(req, duration, &cred)
+ .map_err(new_request_sign_error)
+ }
+
#[inline]
pub async fn send(&self, req: Request<AsyncBody>) ->
Result<Response<IncomingAsyncBody>> {
self.client.send(req).await
@@ -91,6 +104,20 @@ impl ObsCore {
if_match: Option<&str>,
if_none_match: Option<&str>,
) -> Result<Response<IncomingAsyncBody>> {
+ let mut req = self.obs_get_object_request(path, range, if_match,
if_none_match)?;
+
+ self.sign(&mut req).await?;
+
+ self.send(req).await
+ }
+
+ pub fn obs_get_object_request(
+ &self,
+ path: &str,
+ range: BytesRange,
+ if_match: Option<&str>,
+ if_none_match: Option<&str>,
+ ) -> Result<Request<AsyncBody>> {
let p = build_abs_path(&self.root, path);
let url = format!("{}/{}", self.endpoint, percent_encode_path(&p));
@@ -109,13 +136,11 @@ impl ObsCore {
req = req.header(IF_NONE_MATCH, if_none_match);
}
- let mut req = req
+ let req = req
.body(AsyncBody::Empty)
.map_err(new_request_build_error)?;
- self.sign(&mut req).await?;
-
- self.send(req).await
+ Ok(req)
}
pub fn obs_put_object_request(
@@ -148,12 +173,25 @@ impl ObsCore {
Ok(req)
}
- pub async fn obs_get_head_object(
+ pub async fn obs_head_object(
&self,
path: &str,
if_match: Option<&str>,
if_none_match: Option<&str>,
) -> Result<Response<IncomingAsyncBody>> {
+ let mut req = self.obs_head_object_request(path, if_match,
if_none_match)?;
+
+ self.sign(&mut req).await?;
+
+ self.send(req).await
+ }
+
+ pub fn obs_head_object_request(
+ &self,
+ path: &str,
+ if_match: Option<&str>,
+ if_none_match: Option<&str>,
+ ) -> Result<Request<AsyncBody>> {
let p = build_abs_path(&self.root, path);
let url = format!("{}/{}", self.endpoint, percent_encode_path(&p));
@@ -171,13 +209,11 @@ impl ObsCore {
req = req.header(IF_NONE_MATCH, if_none_match);
}
- let mut req = req
+ let req = req
.body(AsyncBody::Empty)
.map_err(new_request_build_error)?;
- self.sign(&mut req).await?;
-
- self.send(req).await
+ Ok(req)
}
pub async fn obs_delete_object(&self, path: &str) ->
Result<Response<IncomingAsyncBody>> {