Skip to content
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
18 changes: 14 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ doctest = false

[dependencies]
tokio = { version = "1.0", features = ["sync"] }
pyo3 = { version = "0.23.0", features = ["anyhow", "indexmap", "multiple-pymethods", "abi3-py39", "generate-import-lib", "experimental-inspect"] }
pyo3 = { version = "0.23.0", features = [
"anyhow",
"indexmap",
"multiple-pymethods",
"abi3-py39",
"generate-import-lib",
"experimental-inspect",
] }
pyo3-async-runtimes = { version = "0.23.0", features = ["tokio-runtime"] }
pyo3-stub-gen = "0.7.0"
anyhow = "1.0"
Expand All @@ -27,15 +34,18 @@ indexmap = { version = "2.7.0", features = ["serde"] }
cookie = "0.18.0"
arc-swap = "1.7.1"
url = "2.5"
rquest = { version = "2.1.5", features = ["full", "websocket"] }
rquest = { version = "2.1.5", features = ["full", "websocket", "hickory-dns"] }
futures-util = { version = "0.3.0", default-features = false }

[target.'cfg(not(target_env = "msvc"))'.dependencies]
jemallocator = { package = "tikv-jemallocator", version = "0.6", features = ["disable_initial_exec_tls", "unprefixed_malloc_on_supported_platforms"] }
jemallocator = { package = "tikv-jemallocator", version = "0.6", features = [
"disable_initial_exec_tls",
"unprefixed_malloc_on_supported_platforms",
] }

[profile.release]
lto = true
opt-level = 3
codegen-units = 1
strip = true
panic = "abort"
panic = "abort"
1 change: 1 addition & 0 deletions examples/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ async def main():
client = Client(
impersonate=Impersonate.Firefox133,
user_agent="rnet",
async_dns=True,
)
resp = await client.get("https://httpbin.org/stream/20")
print("Status Code: ", resp.status_code)
Expand Down
10 changes: 9 additions & 1 deletion src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
dns,
error::{
wrap_invali_header_name_error, wrap_invali_header_value_error, wrap_rquest_error,
wrap_url_parse_error,
Expand All @@ -12,6 +13,7 @@ use arc_swap::{ArcSwap, Guard};
use pyo3::prelude::*;
use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods};
use rquest::{
dns::LookupIpStrategy,
header::{HeaderMap, HeaderName, HeaderValue},
redirect::Policy,
Url,
Expand Down Expand Up @@ -466,7 +468,7 @@ impl Client {
#[pyo3(signature = (**kwds))]
fn new(mut kwds: Option<ClientParams>) -> PyResult<Client> {
let params = kwds.get_or_insert_default();
let mut builder = rquest::Client::builder();
let mut builder = rquest::Client::builder().no_hickory_dns();

// Impersonation options.
if let Some(impersonate) = params.impersonate.take() {
Expand Down Expand Up @@ -534,6 +536,12 @@ impl Client {
// Cookie store options.
apply_option!(apply_if_some, builder, params.cookie_store, cookie_store);

// Async resolver options.
if params.async_dns.unwrap_or(false) {
let hickory_dns_resolver = dns::get_or_try_init(LookupIpStrategy::Ipv4AndIpv6)?;
builder = builder.dns_resolver(hickory_dns_resolver);
}

// Timeout options.
apply_option!(
apply_transformed_option,
Expand Down
48 changes: 48 additions & 0 deletions src/dns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::error::DNSResolverError;
use rquest::dns::{HickoryDnsResolver, LookupIpStrategy};
use std::sync::{Arc, OnceLock};

/// Initializes and returns a DNS resolver with the specified strategy.
///
/// This function initializes a global DNS resolver using the provided lookup IP strategy.
/// If the DNS resolver has already been initialized, it returns the existing instance.
///
/// # Arguments
///
/// * `strategy` - An optional `LookupIpStrategy` to use for the DNS resolver.
///
/// # Returns
///
/// A `Result` containing an `Arc` to the `HickoryDnsResolver` instance, or an error if initialization fails.
///
/// # Errors
///
/// This function returns an error if the DNS resolver fails to initialize.
///
/// # Examples
///
/// ```rust
/// use rnet::dns::get_or_try_init;
/// use rquest::dns::LookupIpStrategy;
///
/// let resolver = get_or_try_init(LookupIpStrategy::default()).unwrap();
/// ```
pub fn get_or_try_init<S>(strategy: S) -> crate::Result<Arc<HickoryDnsResolver>>
where
S: Into<Option<LookupIpStrategy>>,
{
static DNS_RESOLVER: OnceLock<Result<Arc<HickoryDnsResolver>, &'static str>> = OnceLock::new();

DNS_RESOLVER
.get_or_init(move || {
HickoryDnsResolver::new(strategy.into())
.map(Arc::new)
.map_err(|err| {
eprintln!("failed to initialize the DNS resolver: {}", err);
"failed to initialize the DNS resolver"
})
})
.as_ref()
.map(Arc::clone)
.map_err(DNSResolverError::new_err)
}
1 change: 1 addition & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Potential solutions:
"#;

create_exception!(exceptions, BorrowingError, PyRuntimeError);
create_exception!(exceptions, DNSResolverError, PyRuntimeError);

create_exception!(exceptions, BaseError, PyException);
create_exception!(exceptions, BodyError, BaseError);
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod client;
mod dns;
mod error;
mod param;
mod response;
Expand Down
5 changes: 5 additions & 0 deletions src/param/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ pub struct ClientParams {
#[pyo3(get)]
pub cookie_store: Option<bool>,

/// Whether to use async DNS resolver.
#[pyo3(get)]
pub async_dns: Option<bool>,

// ========= Timeout options =========
/// The timeout to use for the request. (in seconds)
#[pyo3(get)]
Expand Down Expand Up @@ -234,6 +238,7 @@ impl<'py> FromPyObject<'py> for ClientParams {
extract_option!(ob, params, referer);
extract_option!(ob, params, allow_redirects);
extract_option!(ob, params, cookie_store);
extract_option!(ob, params, async_dns);

extract_option!(ob, params, timeout);
extract_option!(ob, params, connect_timeout);
Expand Down