Skip to content

Commit

Permalink
Log netrc parsing error (astral-sh#8364)
Browse files Browse the repository at this point in the history
## Summary

Resolves astral-sh#7685

## Test Plan

```console
$ echo "this is an invalid netrc" > .netrc
$ NETRC=.netrc cargo run -- pip install anyio --index-url https://pypi-proxy.fly.dev/basic-auth/simple --strict -v
DEBUG uv 0.4.24 (f4d5fba 2024-10-19)
DEBUG Searching for default Python interpreter in system path or `py` launcher
DEBUG Found `cpython-3.11.2-windows-x86_64-none` at `D:\Projects\Rust\uv\.venv\Scripts\python.exe` (virtual environment)
DEBUG Using Python 3.11.2 environment at .venv
DEBUG Acquired lock for `.venv`
DEBUG At least one requirement is not satisfied: anyio
DEBUG Using request timeout of 30s
DEBUG Solving with installed Python version: 3.11.2
DEBUG Solving with target Python version: >=3.11.2
DEBUG Adding direct dependency: anyio*
DEBUG No cache entry for: https://pypi-proxy.fly.dev/basic-auth/simple/anyio/
WARN Error reading netrc file: parsing error: bad toplevel token 'this' (line 1) in the file '.netrc'
DEBUG Searching for a compatible version of anyio (*)
DEBUG No compatible version found for: anyio
  × No solution found when resolving dependencies:
  ╰─▶ Because anyio was not found in the package registry and you require anyio, we can conclude that your
      requirements are unsatisfiable.

      hint: An index URL (https://pypi-proxy.fly.dev/basic-auth/simple) could not be queried due to a lack of valid
      authentication credentials (401 Unauthorized).
DEBUG Released lock at `D:\Projects\Rust\uv\.venv\.lock`
error: process didn't exit successfully: `target\debug\uv.exe pip install anyio --index-url https://pypi-proxy.fly.dev/basic-auth/simple --strict -v` (exit code: 1)

```
  • Loading branch information
j178 authored and MtkN1 committed Oct 21, 2024
1 parent e17026d commit 3ba3754
Showing 1 changed file with 46 additions and 8 deletions.
54 changes: 46 additions & 8 deletions crates/uv-auth/src/middleware.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::Arc;
use std::sync::{Arc, LazyLock};

use http::{Extensions, StatusCode};
use url::Url;
Expand All @@ -12,14 +12,48 @@ use anyhow::{anyhow, format_err};
use netrc::Netrc;
use reqwest::{Request, Response};
use reqwest_middleware::{Error, Middleware, Next};
use tracing::{debug, trace};
use tracing::{debug, trace, warn};

/// Strategy for loading netrc files.
enum NetrcMode {
Automatic(LazyLock<Option<Netrc>>),
Enabled(Netrc),
Disabled,
}

impl Default for NetrcMode {
fn default() -> Self {
NetrcMode::Automatic(LazyLock::new(|| match Netrc::new() {
Ok(netrc) => Some(netrc),
Err(netrc::Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
debug!("No netrc file found");
None
}
Err(err) => {
warn!("Error reading netrc file: {err}");
None
}
}))
}
}

impl NetrcMode {
/// Get the parsed netrc file if enabled.
fn get(&self) -> Option<&Netrc> {
match self {
NetrcMode::Automatic(lock) => lock.as_ref(),
NetrcMode::Enabled(netrc) => Some(netrc),
NetrcMode::Disabled => None,
}
}
}

/// A middleware that adds basic authentication to requests.
///
/// Uses a cache to propagate credentials from previously seen requests and
/// fetches credentials from a netrc file and the keyring.
pub struct AuthMiddleware {
netrc: Option<Netrc>,
netrc: NetrcMode,
keyring: Option<KeyringProvider>,
cache: Option<CredentialsCache>,
/// We know that the endpoint needs authentication, so we don't try to send an unauthenticated
Expand All @@ -30,19 +64,23 @@ pub struct AuthMiddleware {
impl AuthMiddleware {
pub fn new() -> Self {
Self {
netrc: Netrc::new().ok(),
netrc: NetrcMode::default(),
keyring: None,
cache: None,
only_authenticated: false,
}
}

/// Configure the [`Netrc`] credential file to use.
/// Configure the [`netrc::Netrc`] credential file to use.
///
/// `None` disables authentication via netrc.
#[must_use]
pub fn with_netrc(mut self, netrc: Option<Netrc>) -> Self {
self.netrc = netrc;
pub fn with_netrc(mut self, netrc: Option<netrc::Netrc>) -> Self {
self.netrc = if let Some(netrc) = netrc {
NetrcMode::Enabled(netrc)
} else {
NetrcMode::Disabled
};
self
}

Expand Down Expand Up @@ -361,7 +399,7 @@ impl AuthMiddleware {
}

// Netrc support based on: <https://github.com/gribouille/netrc>.
let credentials = if let Some(credentials) = self.netrc.as_ref().and_then(|netrc| {
let credentials = if let Some(credentials) = self.netrc.get().and_then(|netrc| {
debug!("Checking netrc for credentials for {url}");
Credentials::from_netrc(
netrc,
Expand Down

0 comments on commit 3ba3754

Please sign in to comment.