Skip to content

Commit f4d5fba

Browse files
committed
Use LazyLock to parse netrc only once
1 parent cfca400 commit f4d5fba

File tree

1 file changed

+41
-37
lines changed

1 file changed

+41
-37
lines changed

crates/uv-auth/src/middleware.rs

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::Arc;
1+
use std::sync::{Arc, LazyLock};
22

33
use http::{Extensions, StatusCode};
44
use url::Url;
@@ -16,11 +16,38 @@ use tracing::{debug, trace, warn};
1616

1717
/// Strategy for loading netrc files.
1818
enum NetrcMode {
19-
Automatic,
20-
Enabled(netrc::Netrc),
19+
Automatic(LazyLock<Option<Netrc>>),
20+
Enabled(Netrc),
2121
Disabled,
2222
}
2323

24+
impl Default for NetrcMode {
25+
fn default() -> Self {
26+
NetrcMode::Automatic(LazyLock::new(|| match Netrc::new() {
27+
Ok(netrc) => Some(netrc),
28+
Err(netrc::Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
29+
debug!("No netrc file found");
30+
None
31+
}
32+
Err(err) => {
33+
warn!("Error reading netrc file: {err}");
34+
None
35+
}
36+
}))
37+
}
38+
}
39+
40+
impl NetrcMode {
41+
/// Get the parsed netrc file if enabled.
42+
fn get(&self) -> Option<&Netrc> {
43+
match self {
44+
NetrcMode::Automatic(lock) => lock.as_ref(),
45+
NetrcMode::Enabled(netrc) => Some(netrc),
46+
NetrcMode::Disabled => None,
47+
}
48+
}
49+
}
50+
2451
/// A middleware that adds basic authentication to requests.
2552
///
2653
/// Uses a cache to propagate credentials from previously seen requests and
@@ -37,7 +64,7 @@ pub struct AuthMiddleware {
3764
impl AuthMiddleware {
3865
pub fn new() -> Self {
3966
Self {
40-
netrc: NetrcMode::Automatic,
67+
netrc: NetrcMode::default(),
4168
keyring: None,
4269
cache: None,
4370
only_authenticated: false,
@@ -372,39 +399,16 @@ impl AuthMiddleware {
372399
}
373400

374401
// Netrc support based on: <https://github.com/gribouille/netrc>.
375-
let credentials = if let Some(credentials) = match self.netrc {
376-
NetrcMode::Enabled(ref netrc) => {
377-
debug!("Checking netrc for credentials for {url}");
378-
Credentials::from_netrc(
379-
netrc,
380-
url,
381-
credentials
382-
.as_ref()
383-
.and_then(|credentials| credentials.username()),
384-
)
385-
}
386-
NetrcMode::Automatic => match Netrc::new() {
387-
Ok(netrc) => {
388-
debug!("Checking netrc for credentials for {url}");
389-
Credentials::from_netrc(
390-
&netrc,
391-
url,
392-
credentials
393-
.as_ref()
394-
.and_then(|credentials| credentials.username()),
395-
)
396-
}
397-
Err(netrc::Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
398-
debug!("No netrc file found");
399-
None
400-
}
401-
Err(err) => {
402-
warn!("Error reading netrc file: {err}");
403-
None
404-
}
405-
},
406-
NetrcMode::Disabled => None,
407-
} {
402+
let credentials = if let Some(credentials) = self.netrc.get().and_then(|netrc| {
403+
debug!("Checking netrc for credentials for {url}");
404+
Credentials::from_netrc(
405+
netrc,
406+
url,
407+
credentials
408+
.as_ref()
409+
.and_then(|credentials| credentials.username()),
410+
)
411+
}) {
408412
debug!("Found credentials in netrc file for {url}");
409413
Some(credentials)
410414
// N.B. The keyring provider performs lookups for the exact URL then

0 commit comments

Comments
 (0)