Disable tcp_nodelay for reqwest::Client and add rate limiting for https requests (#458)

This commit is contained in:
Jiahao XU 2022-10-07 15:51:34 +11:00 committed by GitHub
parent 8398ec2d4b
commit 76bc030f90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 243 additions and 99 deletions

View file

@ -29,7 +29,6 @@ dirs = "4.0.0"
log = "0.4.17"
miette = "5.3.0"
mimalloc = { version = "0.1.29", default-features = false, optional = true }
reqwest = { version = "0.11.12", default-features = false }
semver = "1.0.14"
simplelog = "0.12.0"
tempfile = "3.3.0"

View file

@ -1,13 +1,19 @@
use std::{ffi::OsString, path::PathBuf};
use std::{
ffi::OsString,
fmt,
num::{NonZeroU64, ParseIntError},
path::PathBuf,
str::FromStr,
};
use binstalk::{
errors::BinstallError,
helpers::remote::tls::Version,
manifests::cargo_toml_binstall::PkgFmt,
ops::resolve::{CrateName, VersionReqExt},
};
use clap::{Parser, ValueEnum};
use log::LevelFilter;
use reqwest::tls::Version;
use semver::VersionReq;
#[derive(Debug, Parser)]
@ -108,6 +114,21 @@ pub struct Args {
#[clap(help_heading = "Overrides", long)]
pub pkg_url: Option<String>,
/// Override the rate limit duration.
///
/// By default, cargo-binstall allows one request per 5 ms.
///
/// Example:
///
/// - `6`: Set the duration to 6ms, allows one request per 6 ms.
///
/// - `6/2`: Set the duration to 6ms and request_count to 2,
/// allows 2 requests per 6ms.
///
/// Both duration and request count must not be 0.
#[clap(help_heading = "Overrides", long, default_value_t = RateLimit::default())]
pub rate_limit: RateLimit,
/// Disable symlinking / versioned updates.
///
/// By default, Binstall will install a binary named `<name>-<version>` in the install path, and
@ -218,6 +239,45 @@ impl From<TLSVersion> for Version {
}
}
#[derive(Copy, Clone, Debug)]
pub struct RateLimit {
pub duration: NonZeroU64,
pub request_count: NonZeroU64,
}
impl fmt::Display for RateLimit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/{}", self.duration, self.request_count)
}
}
impl FromStr for RateLimit {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(if let Some((first, second)) = s.split_once('/') {
Self {
duration: first.parse()?,
request_count: second.parse()?,
}
} else {
Self {
duration: s.parse()?,
..Default::default()
}
})
}
}
impl Default for RateLimit {
fn default() -> Self {
Self {
duration: NonZeroU64::new(5).unwrap(),
request_count: NonZeroU64::new(1).unwrap(),
}
}
}
pub fn parse() -> Result<Args, BinstallError> {
// Filter extraneous arg when invoked by cargo
// `cargo run -- --help` gives ["target/debug/cargo-binstall", "--help"]

View file

@ -3,10 +3,7 @@ use std::{fs, path::Path, sync::Arc, time::Duration};
use binstalk::{
errors::BinstallError,
get_desired_targets,
helpers::{
jobserver_client::LazyJobserverClient, remote::create_reqwest_client,
tasks::AutoAbortJoinHandle,
},
helpers::{jobserver_client::LazyJobserverClient, remote::Client, tasks::AutoAbortJoinHandle},
manifests::{
binstall_crates_v1::Records, cargo_crates_v1::CratesToml, cargo_toml_binstall::PkgOverride,
},
@ -31,12 +28,20 @@ pub async fn install_crates(mut args: Args, jobserver_client: LazyJobserverClien
// Launch target detection
let desired_targets = get_desired_targets(args.targets.take());
let rate_limit = args.rate_limit;
// Initialize reqwest client
let client = create_reqwest_client(args.min_tls_version.map(|v| v.into()))?;
let client = Client::new(
args.min_tls_version.map(|v| v.into()),
Duration::from_millis(rate_limit.duration.get()),
rate_limit.request_count,
)?;
// Build crates.io api client
let crates_io_api_client =
crates_io_api::AsyncClient::with_http_client(client.clone(), Duration::from_millis(100));
let crates_io_api_client = crates_io_api::AsyncClient::with_http_client(
client.get_inner().clone(),
Duration::from_millis(100),
);
// Initialize UI thread
let mut uithread = UIThread::new(!args.no_confirm);