Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions worker/src/r2/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl<'bucket> GetOptionsBuilder<'bucket> {
}
}

/// You can pass an [Conditional] object to [GetOptionsBuilder]. If the condition check fails,
/// You can pass an [Conditional] object to [GetOptionsBuilder] or [PutOptionsBuilder]. If the condition check fails,
/// the body will not be returned. This will make [get](crate::r2::Bucket::get) have lower latency.
///
/// For more information about conditional requests, refer to [RFC 7232](https://datatracker.ietf.org/doc/html/rfc7232).
Expand Down Expand Up @@ -172,6 +172,7 @@ pub struct PutOptionsBuilder<'bucket> {
pub(crate) custom_metadata: Option<HashMap<String, String>>,
pub(crate) checksum: Option<Vec<u8>>,
pub(crate) checksum_algorithm: String,
pub(crate) only_if: Option<Conditional>,
}

impl<'bucket> PutOptionsBuilder<'bucket> {
Expand Down Expand Up @@ -218,15 +219,25 @@ impl<'bucket> PutOptionsBuilder<'bucket> {
self.checksum_set("sha512", bytes)
}

/// Specifies that the object should only be returned given satisfaction of certain conditions
/// in the [Conditional]. Refer to [Conditional operations](https://developers.cloudflare.com/r2/runtime-apis/#conditional-operations).
pub fn only_if(mut self, only_if: Conditional) -> Self {
self.only_if = Some(only_if);
self
}

/// Executes the PUT operation on the R2 bucket.
pub async fn execute(self) -> Result<Object> {
///
/// If the condition check fails, `None` will be returned instead of an [`Object`].
pub async fn execute(self) -> Result<Option<Object>> {
let value: JsValue = self.value.into();
let name: String = self.key;

let put_promise = self.edge_bucket.put(
name,
value,
js_object! {
"onlyIf" => self.only_if.map(JsObject::from),
"httpMetadata" => self.http_metadata.map(JsObject::from),
"customMetadata" => match self.custom_metadata {
Some(metadata) => {
Expand All @@ -246,14 +257,21 @@ impl<'bucket> PutOptionsBuilder<'bucket> {
}
.into(),
)?;
let res: EdgeR2Object = JsFuture::from(put_promise).await?.into();

let value = JsFuture::from(put_promise).await?;

if value.is_null() {
return Ok(None);
}

let res: EdgeR2Object = value.into();
let inner = if JsString::from("bodyUsed").js_in(&res) {
ObjectInner::Body(res.unchecked_into())
} else {
ObjectInner::NoBody(res)
};

Ok(Object { inner })
Ok(Some(Object { inner }))
}
}

Expand Down Expand Up @@ -357,6 +375,7 @@ pub struct ListOptionsBuilder<'bucket> {
pub(crate) edge_bucket: &'bucket EdgeR2Bucket,
pub(crate) limit: Option<u32>,
pub(crate) prefix: Option<String>,
pub(crate) start_after: Option<String>,
pub(crate) cursor: Option<String>,
pub(crate) delimiter: Option<String>,
pub(crate) include: Option<Vec<Include>>,
Expand All @@ -375,6 +394,12 @@ impl<'bucket> ListOptionsBuilder<'bucket> {
self
}

/// Start listing after this key.
pub fn start_after(mut self, start_after: impl Into<String>) -> Self {
self.start_after = Some(start_after.into());
self
}

/// An opaque token that indicates where to continue listing objects from. A cursor can be
/// retrieved from a previous list operation.
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
Expand Down Expand Up @@ -415,6 +440,7 @@ impl<'bucket> ListOptionsBuilder<'bucket> {
js_object! {
"limit" => self.limit,
"prefix" => self.prefix,
"startAfter" => self.start_after.map(JsValue::from),
"cursor" => self.cursor,
"delimiter" => self.delimiter,
"include" => self
Expand Down
2 changes: 2 additions & 0 deletions worker/src/r2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl Bucket {
custom_metadata: None,
checksum: None,
checksum_algorithm: "md5".into(),
only_if: None,
}
}

Expand All @@ -86,6 +87,7 @@ impl Bucket {
edge_bucket: &self.inner,
limit: None,
prefix: None,
start_after: None,
cursor: None,
delimiter: None,
include: None,
Expand Down
Loading