Skip to content

Commit

Permalink
refactor: reduce number of string allocations when signing requests
Browse files Browse the repository at this point in the history
  • Loading branch information
paolobarbolini authored and guerinoni committed Dec 31, 2024
1 parent 66982f2 commit e392fe6
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl Bucket {
///
/// Returns a `ParseError` if the object is not a valid path.
pub fn object_url(&self, object: &str) -> Result<Url, ParseError> {
let object = percent_encode_path(object);
let object: Cow<'_, str> = percent_encode_path(object).into();
self.base_url.join(&object)
}
}
Expand Down
38 changes: 22 additions & 16 deletions src/signing/canonical_request.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt;

use url::Url;

use super::util::percent_encode;
Expand All @@ -23,15 +25,15 @@ where
string.push_str(url.path());
string.push('\n');

canonical_query_string(query_string, &mut string);
canonical_query_string(query_string, &mut string).expect("String writer panicked");

string.push('\n');

canonical_headers(headers, &mut string);
canonical_headers(headers, &mut string).expect("String writer panicked");

string.push('\n');

signed_headers_(signed_headers, &mut string);
signed_headers_(signed_headers, &mut string).expect("String writer panicked");

string.push('\n');

Expand All @@ -40,7 +42,7 @@ where
string
}

fn canonical_query_string<'a, Q>(query_string: Q, string: &mut String)
fn canonical_query_string<'a, Q>(query_string: Q, mut out: impl fmt::Write) -> fmt::Result
where
Q: Iterator<Item = (&'a str, &'a str)>,
{
Expand All @@ -49,29 +51,31 @@ where
if first {
first = false;
} else {
string.push('&');
out.write_char('&')?;
}

string.push_str(&percent_encode(key));
string.push('=');
string.push_str(&percent_encode(val));
write!(out, "{}={}", percent_encode(key), percent_encode(val))?;
}

Ok(())
}

fn canonical_headers<'a, H>(headers: H, string: &mut String)
fn canonical_headers<'a, H>(headers: H, mut out: impl fmt::Write) -> fmt::Result
where
H: Iterator<Item = (&'a str, &'a str)>,
{
for (key, val) in headers {
string.push_str(key);
string.push(':');
string.push_str(val.trim());
out.write_str(key)?;
out.write_char(':')?;
out.write_str(val.trim())?;

string.push('\n');
out.write_char('\n')?;
}

Ok(())
}

fn signed_headers_<'a, H>(signed_headers: H, string: &mut String)
fn signed_headers_<'a, H>(signed_headers: H, mut out: impl fmt::Write) -> fmt::Result
where
H: Iterator<Item = &'a str>,
{
Expand All @@ -80,11 +84,13 @@ where
if first {
first = false;
} else {
string.push(';');
out.write_char(';')?;
}

string.push_str(key);
out.write_str(key)?;
}

Ok(())
}

#[cfg(test)]
Expand Down
10 changes: 6 additions & 4 deletions src/signing/util.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::{borrow::Cow, fmt::Display};

use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
use url::Url;

Expand Down Expand Up @@ -36,12 +38,12 @@ pub const FRAGMENT: &AsciiSet = &CONTROLS

pub const FRAGMENT_SLASH: &AsciiSet = &FRAGMENT.add(b'/');

pub fn percent_encode(val: &str) -> String {
utf8_percent_encode(val, FRAGMENT_SLASH).to_string()
pub fn percent_encode(val: &str) -> impl Display + Into<Cow<'_, str>> + '_ {
utf8_percent_encode(val, FRAGMENT_SLASH)
}

pub fn percent_encode_path(val: &str) -> String {
utf8_percent_encode(val, FRAGMENT).to_string()
pub fn percent_encode_path(val: &str) -> impl Display + Into<Cow<'_, str>> + '_ {
utf8_percent_encode(val, FRAGMENT)
}

pub fn add_query_params<'a, Q>(mut url: Url, params: Q) -> Url
Expand Down

0 comments on commit e392fe6

Please sign in to comment.