Skip to content
This repository has been archived by the owner on Feb 7, 2025. It is now read-only.

refractor(tls/settings): Generate configuration using builder mode #121

Merged
merged 2 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu"]

[features]
default = ["boring-tls", "http2"]
default = ["boring-tls"]

full = [
"boring-tls",
Expand All @@ -31,12 +31,9 @@ full = [
"stream",
"cookies",
"socks",
"http2",
"hickory-dns",
]

http2 = ["h2", "hyper/http2"]

blocking = ["futures-util/io", "tokio/sync"]

websocket = ["async-tungstenite", "tokio-util/compat"]
Expand Down Expand Up @@ -76,6 +73,7 @@ boring-tls = [
"dep:linked_hash_set",
"dep:tower-layer",
"dep:antidote",
"dep:typed-builder"
]

# When enabled, disable using the cached SYS_PROXIES.
Expand Down Expand Up @@ -104,10 +102,11 @@ http-body = "0.4.6"
hyper = { package = "rhyper", version = "0.14", default-features = false, features = [
"tcp",
"http1",
"http2",
"client",
"runtime",
] }
h2 = { package = "rh2", version = "0.3", optional = true }
h2 = { package = "rh2", version = "0.3" }
log = "0.4"
mime = "0.3.17"
percent-encoding = "2.3"
Expand All @@ -131,6 +130,9 @@ linked_hash_set = { version = "0.1", optional = true }
tower-layer = { version = "0.3", optional = true }
antidote = { version = "1", optional = true }

# boring-tls extension builder
typed-builder = { version = "0.19", optional = true }

## cookies
cookie_crate = { version = "0.18", package = "cookie", optional = true }
cookie_store = { version = "0.21", optional = true }
Expand Down
68 changes: 35 additions & 33 deletions examples/pre_configured_tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,47 @@ use std::error::Error;
use boring::ssl::{SslConnector, SslMethod};
use http::HeaderValue;
use rquest::{
tls::{Http2FrameSettings, TlsExtensionSettings, TlsSettings, Version},
tls::{Http2FrameSettings, TlsExtensionSettings, TlsSettings},
HttpVersionPref,
};
use rquest::{PseudoOrder, SettingsOrder, StreamDependency, StreamId};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let settings = TlsSettings {
builder: SslConnector::builder(SslMethod::tls_client())?,
extension: TlsExtensionSettings {
tls_sni: true,
http_version_pref: HttpVersionPref::Http2,
min_tls_version: Some(Version::TLS_1_0),
max_tls_version: Some(Version::TLS_1_3),
application_settings: true,
pre_shared_key: true,
enable_ech_grease: true,
permute_extensions: true,
},
http2: Http2FrameSettings {
initial_stream_window_size: Some(6291456),
initial_connection_window_size: Some(15728640),
max_concurrent_streams: Some(1000),
max_header_list_size: Some(262144),
header_table_size: Some(65536),
enable_push: None,
headers_priority: Some(StreamDependency::new(StreamId::zero(), 255, true)),
headers_pseudo_order: Some([
PseudoOrder::Method,
PseudoOrder::Scheme,
PseudoOrder::Authority,
PseudoOrder::Path,
]),
settings_order: Some([
SettingsOrder::InitialWindowSize,
SettingsOrder::MaxConcurrentStreams,
]),
},
};
let settings = TlsSettings::builder()
.builder(SslConnector::builder(SslMethod::tls_client())?)
.extension(
TlsExtensionSettings::builder()
.tls_sni(true)
.http_version_pref(HttpVersionPref::All)
.application_settings(true)
.pre_shared_key(true)
.enable_ech_grease(true)
.permute_extensions(true)
.build(),
)
.http2(
Http2FrameSettings::builder()
.initial_stream_window_size(6291456)
.initial_connection_window_size(15728640)
.max_concurrent_streams(1000)
.max_header_list_size(262144)
.header_table_size(65536)
.enable_push(None)
.headers_priority(StreamDependency::new(StreamId::zero(), 255, true))
.headers_pseudo_order([
PseudoOrder::Method,
PseudoOrder::Scheme,
PseudoOrder::Authority,
PseudoOrder::Path,
])
.settings_order([
SettingsOrder::InitialWindowSize,
SettingsOrder::MaxConcurrentStreams,
])
.build(),
)
.build();

// Build a client with pre-configured TLS settings
let client = rquest::Client::builder()
Expand Down
62 changes: 15 additions & 47 deletions src/async_impl/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use http::header::{
use http::uri::Scheme;
use http::{HeaderName, Uri};
use hyper::client::{HttpConnector, ResponseFuture as HyperResponseFuture};
#[cfg(feature = "http2")]
#[cfg(feature = "boring-tls")]
use hyper::{PseudoOrder, SettingsOrder, StreamDependency};
use pin_project_lite::pin_project;
use std::future::Future;
Expand Down Expand Up @@ -68,7 +68,6 @@ pub enum HttpVersionPref {
/// Prefer HTTP/1.1
Http1,
/// Prefer HTTP/2
#[cfg(feature = "http2")]
Http2,
/// Prefer HTTP/1 and HTTP/2
All,
Expand Down Expand Up @@ -98,7 +97,6 @@ struct Config {
cookie_store: Option<Arc<dyn cookie::CookieStore>>,
hickory_dns: bool,
error: Option<crate::Error>,
http_version_pref: HttpVersionPref,
dns_overrides: HashMap<String, Vec<SocketAddr>>,
dns_resolver: Option<Arc<dyn Resolve>>,
builder: hyper::client::Builder,
Expand Down Expand Up @@ -149,7 +147,6 @@ impl ClientBuilder {
hickory_dns: cfg!(feature = "hickory-dns"),
#[cfg(feature = "cookies")]
cookie_store: None,
http_version_pref: HttpVersionPref::All,
dns_overrides: HashMap::new(),
dns_resolver: None,
builder: hyper::Client::builder(),
Expand Down Expand Up @@ -244,10 +241,6 @@ impl ClientBuilder {
.builder
.pool_idle_timeout(config.pool_idle_timeout)
.pool_max_idle_per_host(config.pool_max_idle_per_host);
#[cfg(feature = "http2")]
if matches!(config.http_version_pref, HttpVersionPref::Http2) {
config.builder.http2_only(true);
}

Ok(Client {
inner: Arc::new(ClientRef {
Expand Down Expand Up @@ -296,26 +289,17 @@ impl ClientBuilder {
func(&mut self.config.headers);
self.config.tls.builder = Some(settings.builder);
self.config.tls.extension = settings.extension;
self.config.tls.extension.http_version_pref = self.config.http_version_pref;

// Set the http2 version preference
#[cfg(feature = "http2")]
{
self.http2_initial_stream_window_size(settings.http2.initial_stream_window_size)
.http2_initial_connection_window_size(settings.http2.initial_connection_window_size)
.http2_max_concurrent_streams(settings.http2.max_concurrent_streams)
.http2_max_header_list_size(settings.http2.max_header_list_size)
.http2_header_table_size(settings.http2.header_table_size)
.http2_enable_push(settings.http2.enable_push)
.http2_headers_priority(settings.http2.headers_priority)
.http2_headers_pseudo_order(settings.http2.headers_pseudo_order)
.http2_settings_order(settings.http2.settings_order)
}

#[cfg(not(feature = "http2"))]
{
self
}
self.http2_initial_stream_window_size(settings.http2.initial_stream_window_size)
.http2_initial_connection_window_size(settings.http2.initial_connection_window_size)
.http2_max_concurrent_streams(settings.http2.max_concurrent_streams)
.http2_max_header_list_size(settings.http2.max_header_list_size)
.http2_header_table_size(settings.http2.header_table_size)
.http2_enable_push(settings.http2.enable_push)
.http2_headers_priority(settings.http2.headers_priority)
.http2_headers_pseudo_order(settings.http2.headers_pseudo_order)
.http2_settings_order(settings.http2.settings_order)
}

/// Enable Encrypted Client Hello (Secure SNI)
Expand Down Expand Up @@ -787,33 +771,32 @@ impl ClientBuilder {
}

/// Only use HTTP/1.
/// Default is Http/1.
pub fn http1_only(mut self) -> ClientBuilder {
self.config.http_version_pref = HttpVersionPref::Http1;
self.config.tls.extension.http_version_pref = HttpVersionPref::Http1;
self
}

/// Allow HTTP/0.9 responses
#[cfg(feature = "http2")]
pub fn http09_responses(mut self) -> ClientBuilder {
self.config.builder.http09_responses(true);
self
}

/// Only use HTTP/2.
#[cfg(feature = "http2")]
pub fn http2_prior_knowledge(mut self) -> ClientBuilder {
pub fn http2_only(mut self) -> ClientBuilder {
#[cfg(feature = "boring-tls")]
{
self.config.tls.extension.http_version_pref = HttpVersionPref::Http2;
self.config.builder.http2_only(true);
}
self.config.builder.http2_only(true);

self
}

/// Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP2 stream-level flow control.
///
/// Default is currently 65,535 but may change internally to optimize for common uses.
#[cfg(feature = "http2")]
pub fn http2_initial_stream_window_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
self.config
.builder
Expand All @@ -824,7 +807,6 @@ impl ClientBuilder {
/// Sets the max connection-level flow control for HTTP2
///
/// Default is currently 65,535 but may change internally to optimize for common uses.
#[cfg(feature = "http2")]
pub fn http2_initial_connection_window_size(
mut self,
sz: impl Into<Option<u32>>,
Expand All @@ -839,7 +821,6 @@ impl ClientBuilder {
///
/// Enabling this will override the limits set in `http2_initial_stream_window_size` and
/// `http2_initial_connection_window_size`.
#[cfg(feature = "http2")]
pub fn http2_adaptive_window(mut self, enabled: bool) -> ClientBuilder {
self.config.builder.http2_adaptive_window(enabled);
self
Expand All @@ -848,7 +829,6 @@ impl ClientBuilder {
/// Sets the maximum frame size to use for HTTP2.
///
/// Default is currently 16,384 but may change internally to optimize for common uses.
#[cfg(feature = "http2")]
pub fn http2_max_frame_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
self.config.builder.http2_max_frame_size(sz.into());
self
Expand All @@ -857,7 +837,6 @@ impl ClientBuilder {
/// Sets the maximum concurrent streams to use for HTTP2.
///
/// Passing `None` will do nothing.
#[cfg(feature = "http2")]
pub fn http2_max_concurrent_streams(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
if let Some(max) = sz.into() {
self.config.builder.http2_max_concurrent_streams(max);
Expand All @@ -868,7 +847,6 @@ impl ClientBuilder {
/// Sets the max header list size to use for HTTP2.
///
/// Passing `None` will do nothing.
#[cfg(feature = "http2")]
pub fn http2_max_header_list_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
if let Some(sz) = sz.into() {
self.config.builder.http2_max_header_list_size(sz);
Expand All @@ -879,7 +857,6 @@ impl ClientBuilder {
/// Enables and disables the push feature for HTTP2.
///
/// Passing `None` will do nothing.
#[cfg(feature = "http2")]
pub fn http2_enable_push(mut self, sz: impl Into<Option<bool>>) -> ClientBuilder {
if let Some(sz) = sz.into() {
self.config.builder.http2_enable_push(sz);
Expand All @@ -890,7 +867,6 @@ impl ClientBuilder {
/// Sets the header table size to use for HTTP2.
///
/// Passing `None` will do nothing.
#[cfg(feature = "http2")]
pub fn http2_header_table_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
if let Some(sz) = sz.into() {
self.config.builder.http2_header_table_size(sz);
Expand All @@ -901,7 +877,6 @@ impl ClientBuilder {
/// Sets the pseudo header order for HTTP2.
/// This is an array of 4 elements, each element is a `PseudoOrder` enum.
/// Default is `None`.
#[cfg(feature = "http2")]
pub fn http2_headers_pseudo_order(
mut self,
order: impl Into<Option<[PseudoOrder; 4]>>,
Expand All @@ -912,7 +887,6 @@ impl ClientBuilder {

/// Sets the priority for HTTP2 headers.
/// Default is `None`.
#[cfg(feature = "http2")]
pub fn http2_headers_priority(
mut self,
priority: impl Into<Option<StreamDependency>>,
Expand All @@ -924,7 +898,6 @@ impl ClientBuilder {
/// Sets the settings order for HTTP2.
/// This is an array of 2 elements, each element is a `SettingsOrder` enum.
/// Default is `None`.
#[cfg(feature = "http2")]
pub fn http2_settings_order(
mut self,
order: impl Into<Option<[SettingsOrder; 2]>>,
Expand All @@ -937,7 +910,6 @@ impl ClientBuilder {
///
/// Pass `None` to disable HTTP2 keep-alive.
/// Default is currently disabled.
#[cfg(feature = "http2")]
pub fn http2_keep_alive_interval(
mut self,
interval: impl Into<Option<Duration>>,
Expand All @@ -953,7 +925,6 @@ impl ClientBuilder {
/// If the ping is not acknowledged within the timeout, the connection will be closed.
/// Does nothing if `http2_keep_alive_interval` is disabled.
/// Default is currently disabled.
#[cfg(feature = "http2")]
pub fn http2_keep_alive_timeout(mut self, timeout: Duration) -> ClientBuilder {
self.config.builder.http2_keep_alive_timeout(timeout);
self
Expand All @@ -965,7 +936,6 @@ impl ClientBuilder {
/// If enabled, pings are also sent when no streams are active.
/// Does nothing if `http2_keep_alive_interval` is disabled.
/// Default is `false`.
#[cfg(feature = "http2")]
pub fn http2_keep_alive_while_idle(mut self, enabled: bool) -> ClientBuilder {
self.config.builder.http2_keep_alive_while_idle(enabled);
self
Expand Down Expand Up @@ -1779,7 +1749,6 @@ impl PendingRequest {
}

fn retry_error(mut self: Pin<&mut Self>, err: &(dyn std::error::Error + 'static)) -> bool {
#[cfg(feature = "http2")]
if !is_retryable_error(err) {
return false;
}
Expand Down Expand Up @@ -1819,7 +1788,6 @@ impl PendingRequest {
}
}

#[cfg(feature = "http2")]
fn is_retryable_error(err: &(dyn std::error::Error + 'static)) -> bool {
if let Some(cause) = err.source() {
if let Some(err) = cause.downcast_ref::<h2::Error>() {
Expand Down
Loading
Loading