mirror of https://github.com/astral-sh/uv
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:
parent
bcc3e4f196
commit
9776dc5882
|
|
@ -4606,6 +4606,7 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
"uv-once-map",
|
"uv-once-map",
|
||||||
|
"uv-small-str",
|
||||||
"uv-static",
|
"uv-static",
|
||||||
"wiremock",
|
"wiremock",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
uv-once-map = { workspace = true }
|
uv-once-map = { workspace = true }
|
||||||
|
uv-small-str = { workspace = true }
|
||||||
uv-static = { workspace = true }
|
uv-static = { workspace = true }
|
||||||
|
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt::Formatter;
|
||||||
use std::hash::BuildHasherDefault;
|
use std::hash::BuildHasherDefault;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
@ -41,26 +42,30 @@ impl CredentialsCache {
|
||||||
/// Return the credentials that should be used for a realm and username, if any.
|
/// 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>> {
|
pub(crate) fn get_realm(&self, realm: Realm, username: Username) -> Option<Arc<Credentials>> {
|
||||||
let realms = self.realms.read().unwrap();
|
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 given_username = username.is_some();
|
||||||
let key = (realm, username);
|
let key = (realm, username);
|
||||||
|
|
||||||
let Some(credentials) = realms.get(&key).cloned() else {
|
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;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
if given_username && credentials.password().is_none() {
|
if given_username && credentials.password().is_none() {
|
||||||
// If given a username, don't return password-less credentials
|
// 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;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("Found cached credentials for realm {name}");
|
trace!(
|
||||||
|
"Found cached credentials for realm {}",
|
||||||
|
RealmUsername::from(key)
|
||||||
|
);
|
||||||
Some(credentials)
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,10 @@ impl Credentials {
|
||||||
self.username.clone()
|
self.username.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_username(&self) -> &Username {
|
||||||
|
&self.username
|
||||||
|
}
|
||||||
|
|
||||||
pub fn password(&self) -> Option<&str> {
|
pub fn password(&self) -> Option<&str> {
|
||||||
self.password.as_deref()
|
self.password.as_deref()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ impl Middleware for AuthMiddleware {
|
||||||
None
|
None
|
||||||
} else if let Some(credentials) = self
|
} else if let Some(credentials) = self
|
||||||
.cache()
|
.cache()
|
||||||
.get_url(request.url(), &credentials.to_username())
|
.get_url(request.url(), credentials.as_username())
|
||||||
{
|
{
|
||||||
request = credentials.authenticate(request);
|
request = credentials.authenticate(request);
|
||||||
// Do not insert already-cached credentials
|
// Do not insert already-cached credentials
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{fmt::Display, fmt::Formatter};
|
use std::{fmt::Display, fmt::Formatter};
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
use uv_small_str::SmallString;
|
||||||
|
|
||||||
/// Used to determine if authentication information should be retained on a new URL.
|
/// Used to determine if authentication information should be retained on a new URL.
|
||||||
/// Based on the specification defined in RFC 7235 and 7230.
|
/// 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.
|
// so we do not need any special handling here.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub(crate) struct Realm {
|
pub(crate) struct Realm {
|
||||||
scheme: String,
|
scheme: SmallString,
|
||||||
host: Option<String>,
|
host: Option<SmallString>,
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Url> for Realm {
|
impl From<&Url> for Realm {
|
||||||
fn from(url: &Url) -> Self {
|
fn from(url: &Url) -> Self {
|
||||||
Self {
|
Self {
|
||||||
scheme: url.scheme().to_string(),
|
scheme: SmallString::from(url.scheme()),
|
||||||
host: url.host_str().map(str::to_string),
|
host: url.host_str().map(SmallString::from),
|
||||||
port: url.port(),
|
port: url.port(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue