Skip to content

Commit 24278de

Browse files
committed
refactor: move http handle constructor to its own module
1 parent cacfc22 commit 24278de

File tree

10 files changed

+244
-221
lines changed

10 files changed

+244
-221
lines changed

src/bin/cargo/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,12 @@ fn init_git(config: &Config) {
293293
/// configured to use libcurl instead of the built-in networking support so
294294
/// that those configuration settings can be used.
295295
fn init_git_transports(config: &Config) {
296-
match cargo::ops::needs_custom_http_transport(config) {
296+
match cargo::http::needs_custom_http_transport(config) {
297297
Ok(true) => {}
298298
_ => return,
299299
}
300300

301-
let handle = match cargo::ops::http_handle(config) {
301+
let handle = match cargo::http::http_handle(config) {
302302
Ok(handle) => handle,
303303
Err(..) => return,
304304
};

src/cargo/core/package.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ use crate::core::resolver::{HasDevUnits, Resolve};
2424
use crate::core::source::MaybePackage;
2525
use crate::core::{Dependency, Manifest, PackageId, SourceId, Target};
2626
use crate::core::{SourceMap, Summary, Workspace};
27-
use crate::ops;
2827
use crate::util::config::PackageCacheLock;
2928
use crate::util::errors::{CargoResult, HttpNotSuccessful, DEBUG_HEADERS};
3029
use crate::util::interning::InternedString;
30+
use crate::util::network::http::http_handle_and_timeout;
31+
use crate::util::network::http::HttpTimeout;
3132
use crate::util::network::retry::{Retry, RetryResult};
3233
use crate::util::network::sleep::SleepTracker;
3334
use crate::util::{self, internal, Config, Progress, ProgressStyle};
@@ -348,7 +349,7 @@ pub struct Downloads<'a, 'cfg> {
348349
/// Note that timeout management is done manually here instead of in libcurl
349350
/// because we want to apply timeouts to an entire batch of operations, not
350351
/// any one particular single operation.
351-
timeout: ops::HttpTimeout,
352+
timeout: HttpTimeout,
352353
/// Last time bytes were received.
353354
updated_at: Cell<Instant>,
354355
/// This is a slow-speed check. It is reset to `now + timeout_duration`
@@ -441,7 +442,7 @@ impl<'cfg> PackageSet<'cfg> {
441442

442443
pub fn enable_download<'a>(&'a self) -> CargoResult<Downloads<'a, 'cfg>> {
443444
assert!(!self.downloading.replace(true));
444-
let timeout = ops::HttpTimeout::new(self.config)?;
445+
let timeout = HttpTimeout::new(self.config)?;
445446
Ok(Downloads {
446447
start: Instant::now(),
447448
set: self,
@@ -713,7 +714,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
713714
debug!("downloading {} as {}", id, token);
714715
assert!(self.pending_ids.insert(id));
715716

716-
let (mut handle, _timeout) = ops::http_handle_and_timeout(self.set.config)?;
717+
let (mut handle, _timeout) = http_handle_and_timeout(self.set.config)?;
717718
handle.get(true)?;
718719
handle.url(&url)?;
719720
handle.follow_location(true)?; // follow redirects

src/cargo/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ use anyhow::Error;
150150
use log::debug;
151151

152152
pub use crate::util::errors::{AlreadyPrintedError, InternalError, VerboseError};
153+
pub use crate::util::network::http;
153154
pub use crate::util::{indented_lines, CargoResult, CliError, CliResult, Config};
154155
pub use crate::version::version;
155156

src/cargo/ops/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ pub use self::cargo_test::{run_benches, run_tests, TestOptions};
2121
pub use self::cargo_uninstall::uninstall;
2222
pub use self::fix::{fix, fix_exec_rustc, fix_get_proxy_lock_addr, FixOptions};
2323
pub use self::lockfile::{load_pkg_lockfile, resolve_to_string, write_pkg_lockfile};
24-
pub use self::registry::HttpTimeout;
25-
pub use self::registry::{configure_http_handle, http_handle, http_handle_and_timeout};
26-
pub use self::registry::{modify_owners, yank, OwnersOptions, PublishOpts};
27-
pub use self::registry::{needs_custom_http_transport, registry_login, registry_logout, search};
28-
pub use self::registry::{publish, RegistryCredentialConfig};
24+
pub use self::registry::modify_owners;
25+
pub use self::registry::publish;
26+
pub use self::registry::registry_login;
27+
pub use self::registry::registry_logout;
28+
pub use self::registry::search;
29+
pub use self::registry::yank;
30+
pub use self::registry::OwnersOptions;
31+
pub use self::registry::PublishOpts;
32+
pub use self::registry::RegistryCredentialConfig;
2933
pub use self::resolve::{
3034
add_overrides, get_resolved_packages, resolve_with_previous, resolve_ws, resolve_ws_with_opts,
3135
WorkspaceResolve,

src/cargo/ops/registry/mod.rs

Lines changed: 2 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,18 @@ use std::collections::HashSet;
1313
use std::path::PathBuf;
1414
use std::str;
1515
use std::task::Poll;
16-
use std::time::Duration;
1716

1817
use anyhow::{bail, format_err, Context as _};
1918
use crates_io::{self, Registry};
20-
use curl::easy::{Easy, InfoType, SslOpt, SslVersion};
21-
use log::{log, Level};
2219

2320
use crate::core::source::Source;
2421
use crate::core::SourceId;
2522
use crate::sources::{RegistrySource, SourceConfigMap};
2623
use crate::util::auth::{self, Secret};
27-
use crate::util::config::{Config, SslVersionConfig, SslVersionConfigRange};
24+
use crate::util::config::Config;
2825
use crate::util::errors::CargoResult;
29-
use crate::util::network;
26+
use crate::util::network::http::http_handle;
3027
use crate::util::IntoUrl;
31-
use crate::version;
3228

3329
pub use self::login::registry_login;
3430
pub use self::logout::registry_logout;
@@ -158,204 +154,6 @@ fn registry(
158154
))
159155
}
160156

161-
/// Creates a new HTTP handle with appropriate global configuration for cargo.
162-
pub fn http_handle(config: &Config) -> CargoResult<Easy> {
163-
let (mut handle, timeout) = http_handle_and_timeout(config)?;
164-
timeout.configure(&mut handle)?;
165-
Ok(handle)
166-
}
167-
168-
pub fn http_handle_and_timeout(config: &Config) -> CargoResult<(Easy, HttpTimeout)> {
169-
if config.frozen() {
170-
bail!(
171-
"attempting to make an HTTP request, but --frozen was \
172-
specified"
173-
)
174-
}
175-
if config.offline() {
176-
bail!(
177-
"attempting to make an HTTP request, but --offline was \
178-
specified"
179-
)
180-
}
181-
182-
// The timeout option for libcurl by default times out the entire transfer,
183-
// but we probably don't want this. Instead we only set timeouts for the
184-
// connect phase as well as a "low speed" timeout so if we don't receive
185-
// many bytes in a large-ish period of time then we time out.
186-
let mut handle = Easy::new();
187-
let timeout = configure_http_handle(config, &mut handle)?;
188-
Ok((handle, timeout))
189-
}
190-
191-
// Only use a custom transport if any HTTP options are specified,
192-
// such as proxies or custom certificate authorities.
193-
//
194-
// The custom transport, however, is not as well battle-tested.
195-
pub fn needs_custom_http_transport(config: &Config) -> CargoResult<bool> {
196-
Ok(
197-
network::proxy::http_proxy_exists(config.http_config()?, config)
198-
|| *config.http_config()? != Default::default()
199-
|| config.get_env_os("HTTP_TIMEOUT").is_some(),
200-
)
201-
}
202-
203-
/// Configure a libcurl http handle with the defaults options for Cargo
204-
pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<HttpTimeout> {
205-
let http = config.http_config()?;
206-
if let Some(proxy) = network::proxy::http_proxy(http) {
207-
handle.proxy(&proxy)?;
208-
}
209-
if let Some(cainfo) = &http.cainfo {
210-
let cainfo = cainfo.resolve_path(config);
211-
handle.cainfo(&cainfo)?;
212-
}
213-
if let Some(check) = http.check_revoke {
214-
handle.ssl_options(SslOpt::new().no_revoke(!check))?;
215-
}
216-
217-
if let Some(user_agent) = &http.user_agent {
218-
handle.useragent(user_agent)?;
219-
} else {
220-
handle.useragent(&format!("cargo {}", version()))?;
221-
}
222-
223-
fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {
224-
let version = match s {
225-
"default" => SslVersion::Default,
226-
"tlsv1" => SslVersion::Tlsv1,
227-
"tlsv1.0" => SslVersion::Tlsv10,
228-
"tlsv1.1" => SslVersion::Tlsv11,
229-
"tlsv1.2" => SslVersion::Tlsv12,
230-
"tlsv1.3" => SslVersion::Tlsv13,
231-
_ => bail!(
232-
"Invalid ssl version `{s}`,\
233-
choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'."
234-
),
235-
};
236-
Ok(version)
237-
}
238-
239-
// Empty string accept encoding expands to the encodings supported by the current libcurl.
240-
handle.accept_encoding("")?;
241-
if let Some(ssl_version) = &http.ssl_version {
242-
match ssl_version {
243-
SslVersionConfig::Single(s) => {
244-
let version = to_ssl_version(s.as_str())?;
245-
handle.ssl_version(version)?;
246-
}
247-
SslVersionConfig::Range(SslVersionConfigRange { min, max }) => {
248-
let min_version = min
249-
.as_ref()
250-
.map_or(Ok(SslVersion::Default), |s| to_ssl_version(s))?;
251-
let max_version = max
252-
.as_ref()
253-
.map_or(Ok(SslVersion::Default), |s| to_ssl_version(s))?;
254-
handle.ssl_min_max_version(min_version, max_version)?;
255-
}
256-
}
257-
} else if cfg!(windows) {
258-
// This is a temporary workaround for some bugs with libcurl and
259-
// schannel and TLS 1.3.
260-
//
261-
// Our libcurl on Windows is usually built with schannel.
262-
// On Windows 11 (or Windows Server 2022), libcurl recently (late
263-
// 2022) gained support for TLS 1.3 with schannel, and it now defaults
264-
// to 1.3. Unfortunately there have been some bugs with this.
265-
// https://github.com/curl/curl/issues/9431 is the most recent. Once
266-
// that has been fixed, and some time has passed where we can be more
267-
// confident that the 1.3 support won't cause issues, this can be
268-
// removed.
269-
//
270-
// Windows 10 is unaffected. libcurl does not support TLS 1.3 on
271-
// Windows 10. (Windows 10 sorta had support, but it required enabling
272-
// an advanced option in the registry which was buggy, and libcurl
273-
// does runtime checks to prevent it.)
274-
handle.ssl_min_max_version(SslVersion::Default, SslVersion::Tlsv12)?;
275-
}
276-
277-
if let Some(true) = http.debug {
278-
handle.verbose(true)?;
279-
log::debug!("{:#?}", curl::Version::get());
280-
handle.debug_function(|kind, data| {
281-
let (prefix, level) = match kind {
282-
InfoType::Text => ("*", Level::Debug),
283-
InfoType::HeaderIn => ("<", Level::Debug),
284-
InfoType::HeaderOut => (">", Level::Debug),
285-
InfoType::DataIn => ("{", Level::Trace),
286-
InfoType::DataOut => ("}", Level::Trace),
287-
InfoType::SslDataIn | InfoType::SslDataOut => return,
288-
_ => return,
289-
};
290-
let starts_with_ignore_case = |line: &str, text: &str| -> bool {
291-
line[..line.len().min(text.len())].eq_ignore_ascii_case(text)
292-
};
293-
match str::from_utf8(data) {
294-
Ok(s) => {
295-
for mut line in s.lines() {
296-
if starts_with_ignore_case(line, "authorization:") {
297-
line = "Authorization: [REDACTED]";
298-
} else if starts_with_ignore_case(line, "h2h3 [authorization:") {
299-
line = "h2h3 [Authorization: [REDACTED]]";
300-
} else if starts_with_ignore_case(line, "set-cookie") {
301-
line = "set-cookie: [REDACTED]";
302-
}
303-
log!(level, "http-debug: {} {}", prefix, line);
304-
}
305-
}
306-
Err(_) => {
307-
log!(
308-
level,
309-
"http-debug: {} ({} bytes of data)",
310-
prefix,
311-
data.len()
312-
);
313-
}
314-
}
315-
})?;
316-
}
317-
318-
HttpTimeout::new(config)
319-
}
320-
321-
#[must_use]
322-
pub struct HttpTimeout {
323-
pub dur: Duration,
324-
pub low_speed_limit: u32,
325-
}
326-
327-
impl HttpTimeout {
328-
pub fn new(config: &Config) -> CargoResult<HttpTimeout> {
329-
let http_config = config.http_config()?;
330-
let low_speed_limit = http_config.low_speed_limit.unwrap_or(10);
331-
let seconds = http_config
332-
.timeout
333-
.or_else(|| {
334-
config
335-
.get_env("HTTP_TIMEOUT")
336-
.ok()
337-
.and_then(|s| s.parse().ok())
338-
})
339-
.unwrap_or(30);
340-
Ok(HttpTimeout {
341-
dur: Duration::new(seconds, 0),
342-
low_speed_limit,
343-
})
344-
}
345-
346-
pub fn configure(&self, handle: &mut Easy) -> CargoResult<()> {
347-
// The timeout option for libcurl by default times out the entire
348-
// transfer, but we probably don't want this. Instead we only set
349-
// timeouts for the connect phase as well as a "low speed" timeout so
350-
// if we don't receive many bytes in a large-ish period of time then we
351-
// time out.
352-
handle.connect_timeout(self.dur)?;
353-
handle.low_speed_time(self.dur)?;
354-
handle.low_speed_limit(self.low_speed_limit)?;
355-
Ok(())
356-
}
357-
}
358-
359157
/// Gets the SourceId for an index or registry setting.
360158
///
361159
/// The `index` and `reg` values are from the command-line or config settings.

src/cargo/sources/git/oxide.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module contains all code sporting `gitoxide` for operations on `git` repositories and it mirrors
22
//! `utils` closely for now. One day it can be renamed into `utils` once `git2` isn't required anymore.
33
4-
use crate::ops::HttpTimeout;
4+
use crate::util::network::http::HttpTimeout;
55
use crate::util::{human_readable_bytes, network, MetricsCounter, Progress};
66
use crate::{CargoResult, Config};
77
use cargo_util::paths;

src/cargo/sources/registry/http_remote.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Access to a HTTP-based crate registry. See [`HttpRegistry`] for details.
22
33
use crate::core::{PackageId, SourceId};
4-
use crate::ops;
54
use crate::sources::registry::download;
65
use crate::sources::registry::MaybeLock;
76
use crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData};
87
use crate::util::errors::{CargoResult, HttpNotSuccessful, DEBUG_HEADERS};
8+
use crate::util::network::http::http_handle;
99
use crate::util::network::retry::{Retry, RetryResult};
1010
use crate::util::network::sleep::SleepTracker;
1111
use crate::util::{auth, Config, Filesystem, IntoUrl, Progress, ProgressStyle};
@@ -610,7 +610,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
610610
// Looks like we're going to have to do a network request.
611611
self.start_fetch()?;
612612

613-
let mut handle = ops::http_handle(self.config)?;
613+
let mut handle = http_handle(self.config)?;
614614
let full_url = self.full_url(path);
615615
debug!("fetch {}", full_url);
616616
handle.get(true)?;

src/cargo/util/config/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,11 @@ use self::ConfigValue as CV;
6969
use crate::core::compiler::rustdoc::RustdocExternMap;
7070
use crate::core::shell::Verbosity;
7171
use crate::core::{features, CliUnstable, Shell, SourceId, Workspace, WorkspaceRootConfig};
72-
use crate::ops::{self, RegistryCredentialConfig};
72+
use crate::ops::RegistryCredentialConfig;
7373
use crate::util::auth::Secret;
7474
use crate::util::errors::CargoResult;
75+
use crate::util::network::http::configure_http_handle;
76+
use crate::util::network::http::http_handle;
7577
use crate::util::CanonicalUrl;
7678
use crate::util::{internal, toml as cargo_toml};
7779
use crate::util::{try_canonicalize, validate_package_name};
@@ -1706,11 +1708,11 @@ impl Config {
17061708
pub fn http(&self) -> CargoResult<&RefCell<Easy>> {
17071709
let http = self
17081710
.easy
1709-
.try_borrow_with(|| ops::http_handle(self).map(RefCell::new))?;
1711+
.try_borrow_with(|| http_handle(self).map(RefCell::new))?;
17101712
{
17111713
let mut http = http.borrow_mut();
17121714
http.reset();
1713-
let timeout = ops::configure_http_handle(self, &mut http)?;
1715+
let timeout = configure_http_handle(self, &mut http)?;
17141716
timeout.configure(&mut http)?;
17151717
}
17161718
Ok(http)

0 commit comments

Comments
 (0)