Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Extensions to object store GetOptions #7170

Merged
merged 3 commits into from
Feb 27, 2025
Merged
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
4 changes: 2 additions & 2 deletions object_store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ async-trait = "0.1.53"
bytes = "1.0"
chrono = { version = "0.4.34", default-features = false, features = ["clock"] }
futures = "0.3"
http = "1.2.0"
humantime = "2.1"
itertools = "0.14.0"
parking_lot = { version = "0.12" }
Expand All @@ -46,7 +47,6 @@ walkdir = { version = "2", optional = true }
# Cloud storage support
base64 = { version = "0.22", default-features = false, features = ["std"], optional = true }
form_urlencoded = { version = "1.2", optional = true }
http = { version = "1.2.0", optional = true }
http-body-util = { version = "0.1", optional = true }
httparse = { version = "1.8.0", default-features = false, features = ["std"], optional = true }
hyper = { version = "1.2", default-features = false, optional = true }
Expand All @@ -66,7 +66,7 @@ nix = { version = "0.29.0", features = ["fs"] }

[features]
default = ["fs"]
cloud = ["serde", "serde_json", "quick-xml", "hyper", "reqwest", "reqwest/stream", "chrono/serde", "base64", "rand", "ring", "dep:http", "http-body-util", "form_urlencoded", "serde_urlencoded"]
cloud = ["serde", "serde_json", "quick-xml", "hyper", "reqwest", "reqwest/stream", "chrono/serde", "base64", "rand", "ring", "http-body-util", "form_urlencoded", "serde_urlencoded"]
azure = ["cloud", "httparse"]
fs = ["walkdir"]
gcp = ["cloud", "rustls-pemfile"]
Expand Down
7 changes: 7 additions & 0 deletions object_store/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ impl HttpRequestBuilder {
self
}

pub(crate) fn extensions(mut self, extensions: ::http::Extensions) -> Self {
if let Ok(r) = &mut self.request {
*r.extensions_mut() = extensions;
}
self
}

pub(crate) fn header<K, V>(mut self, name: K, value: V) -> Self
where
K: TryInto<HeaderName>,
Expand Down
23 changes: 18 additions & 5 deletions object_store/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,27 +718,40 @@ impl GetOptionsExt for HttpRequestBuilder {
fn with_get_options(mut self, options: GetOptions) -> Self {
use hyper::header::*;

if let Some(range) = options.range {
let GetOptions {
if_match,
if_none_match,
if_modified_since,
if_unmodified_since,
range,
version: _,
head: _,
Comment on lines +727 to +728
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided to unpack the struct to make the forwarding here easier to maintain (so new fields are not forgotten). However we seem to have missed these two.

@tustvold is this a bug? Shouldn't we at least wire up version? And head should probably change the method, but I'm not sure how much will break if we do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version is object store specific what it means and so is handled that way, head requests is likely historical.

I wouldn't object to finding a way to roll the logic into here, but it isn't entirely straightforward to do

extensions,
} = options;

if let Some(range) = range {
self = self.header(RANGE, range.to_string());
}

if let Some(tag) = options.if_match {
if let Some(tag) = if_match {
self = self.header(IF_MATCH, tag);
}

if let Some(tag) = options.if_none_match {
if let Some(tag) = if_none_match {
self = self.header(IF_NONE_MATCH, tag);
}

const DATE_FORMAT: &str = "%a, %d %b %Y %H:%M:%S GMT";
if let Some(date) = options.if_unmodified_since {
if let Some(date) = if_unmodified_since {
self = self.header(IF_UNMODIFIED_SINCE, date.format(DATE_FORMAT).to_string());
}

if let Some(date) = options.if_modified_since {
if let Some(date) = if_modified_since {
self = self.header(IF_MODIFIED_SINCE, date.format(DATE_FORMAT).to_string());
}

self = self.extensions(extensions);

self
}
}
Expand Down
5 changes: 5 additions & 0 deletions object_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,11 @@ pub struct GetOptions {
///
/// <https://datatracker.ietf.org/doc/html/rfc9110#name-head>
pub head: bool,
/// Implementation-specific extensions. Intended for use by [`ObjectStore`] implementations
/// that need to pass context-specific information (like tracing spans) via trait methods.
///
/// These extensions are ignored entirely by backends offered through this crate.
pub extensions: ::http::Extensions,
}

impl GetOptions {
Expand Down
Loading