Skip to content

Commit

Permalink
feat(core): add presign support for obs (#2253)
Browse files Browse the repository at this point in the history
* add presign support for obs

* update based on comment
  • Loading branch information
cuichenli authored May 16, 2023
1 parent a15b9df commit 239d3ed
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 11 deletions.
41 changes: 39 additions & 2 deletions core/src/services/obs/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use crate::*;
/// - [ ] rename
/// - [x] list
/// - [x] scan
/// - [ ] presign
/// - [x] presign
/// - [ ] blocking
///
/// # Configuration
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down
54 changes: 45 additions & 9 deletions core/src/services/obs/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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));
Expand All @@ -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(
Expand Down Expand Up @@ -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));
Expand All @@ -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>> {
Expand Down

0 comments on commit 239d3ed

Please sign in to comment.