Remove some allocations from `uv-auth` (#12077)

## Summary

Use `SmallString`, and no need to allocate a `String` to fetch from the
URLs cache.
This commit is contained in:
Charlie Marsh 2025-03-09 11:28:33 -07:00 committed by GitHub
parent bcc3e4f196
commit 9776dc5882
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 45 additions and 13 deletions

1
Cargo.lock generated
View File

@ -4606,6 +4606,7 @@ dependencies = [
"tracing",
"url",
"uv-once-map",
"uv-small-str",
"uv-static",
"wiremock",
]

View File

@ -11,6 +11,7 @@ workspace = true
[dependencies]
uv-once-map = { workspace = true }
uv-small-str = { workspace = true }
uv-static = { workspace = true }
anyhow = { workspace = true }

View File

@ -1,3 +1,4 @@
use std::fmt::Formatter;
use std::hash::BuildHasherDefault;
use std::sync::Arc;
use std::sync::RwLock;
@ -41,26 +42,30 @@ impl CredentialsCache {
/// Return the credentials that should be used for a realm and username, if any.
pub(crate) fn get_realm(&self, realm: Realm, username: Username) -> Option<Arc<Credentials>> {
let realms = self.realms.read().unwrap();
let name = if let Some(username) = username.as_deref() {
format!("{username}@{realm}")
} else {
realm.to_string()
};
let given_username = username.is_some();
let key = (realm, username);
let Some(credentials) = realms.get(&key).cloned() else {
trace!("No credentials in cache for realm {name}");
trace!(
"No credentials in cache for realm {}",
RealmUsername::from(key)
);
return None;
};
if given_username && credentials.password().is_none() {
// If given a username, don't return password-less credentials
trace!("No password in cache for realm {name}");
trace!(
"No password in cache for realm {}",
RealmUsername::from(key)
);
return None;
}
trace!("Found cached credentials for realm {name}");
trace!(
"Found cached credentials for realm {}",
RealmUsername::from(key)
);
Some(credentials)
}
@ -214,6 +219,26 @@ impl TrieState {
}
}
#[derive(Debug)]
struct RealmUsername(Realm, Username);
impl std::fmt::Display for RealmUsername {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let Self(realm, username) = self;
if let Some(username) = username.as_deref() {
write!(f, "{username}@{realm}")
} else {
write!(f, "{realm}")
}
}
}
impl From<(Realm, Username)> for RealmUsername {
fn from((realm, username): (Realm, Username)) -> Self {
Self(realm, username)
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -84,6 +84,10 @@ impl Credentials {
self.username.clone()
}
pub(crate) fn as_username(&self) -> &Username {
&self.username
}
pub fn password(&self) -> Option<&str> {
self.password.as_deref()
}

View File

@ -194,7 +194,7 @@ impl Middleware for AuthMiddleware {
None
} else if let Some(credentials) = self
.cache()
.get_url(request.url(), &credentials.to_username())
.get_url(request.url(), credentials.as_username())
{
request = credentials.authenticate(request);
// Do not insert already-cached credentials

View File

@ -1,6 +1,7 @@
use std::{fmt::Display, fmt::Formatter};
use url::Url;
use uv_small_str::SmallString;
/// Used to determine if authentication information should be retained on a new URL.
/// Based on the specification defined in RFC 7235 and 7230.
@ -23,16 +24,16 @@ use url::Url;
// so we do not need any special handling here.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct Realm {
scheme: String,
host: Option<String>,
scheme: SmallString,
host: Option<SmallString>,
port: Option<u16>,
}
impl From<&Url> for Realm {
fn from(url: &Url) -> Self {
Self {
scheme: url.scheme().to_string(),
host: url.host_str().map(str::to_string),
scheme: SmallString::from(url.scheme()),
host: url.host_str().map(SmallString::from),
port: url.port(),
}
}