support spoofing the host address

This commit is contained in:
2023-09-29 05:07:51 -04:00
parent 50fd1fe14e
commit 0de1c945f2
2 changed files with 22 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
use std::io::Read; use std::io::Read;
use std::{fmt, time}; use std::{fmt, time};
use std::borrow::Cow;
use url::{form_urlencoded, ParseError, Url}; use url::{form_urlencoded, ParseError, Url};
@@ -32,6 +33,7 @@ pub struct Request {
url: String, url: String,
pub(crate) headers: Vec<Header>, pub(crate) headers: Vec<Header>,
timeout: Option<time::Duration>, timeout: Option<time::Duration>,
spoofed_host: Option<Cow<'static, str>>,
} }
impl fmt::Debug for Request { impl fmt::Debug for Request {
@@ -52,6 +54,7 @@ impl Request {
url, url,
headers: vec![], headers: vec![],
timeout: None, timeout: None,
spoofed_host: None,
} }
} }
@@ -62,6 +65,13 @@ impl Request {
self self
} }
#[inline(always)]
/// Sets overall timeout for the request, overriding agent's configuration if any.
pub fn connection_host(mut self, dns_host: Cow<'static, str>) -> Self {
self.spoofed_host = Some(dns_host);
self
}
/// Sends the request with no body and blocks the caller until done. /// Sends the request with no body and blocks the caller until done.
/// ///
/// Use this with GET, HEAD, OPTIONS or TRACE. It sends neither /// Use this with GET, HEAD, OPTIONS or TRACE. It sends neither
@@ -138,7 +148,7 @@ impl Request {
let request_fn = |req: Request| { let request_fn = |req: Request| {
let reader = payload.into_read(); let reader = payload.into_read();
let unit = Unit::new( let mut unit = Unit::new(
&req.agent, &req.agent,
&req.method, &req.method,
&url, &url,
@@ -147,6 +157,9 @@ impl Request {
deadline, deadline,
); );
// forward the spoofed host address
unit.spoofed_host = req.spoofed_host;
unit::connect(unit, true, reader).map_err(|e| e.url(url.clone())) unit::connect(unit, true, reader).map_err(|e| e.url(url.clone()))
}; };

View File

@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::io::{self, Write}; use std::io::{self, Write};
use std::ops::Range; use std::ops::Range;
@@ -32,6 +33,7 @@ pub(crate) struct Unit {
is_chunked: bool, is_chunked: bool,
headers: Vec<Header>, headers: Vec<Header>,
pub deadline: Option<time::Instant>, pub deadline: Option<time::Instant>,
pub spoofed_host: Option<Cow<'static, str>>,
} }
impl Unit { impl Unit {
@@ -252,8 +254,13 @@ fn connect_inner(
.unwrap(); .unwrap();
let url = &unit.url; let url = &unit.url;
let method = &unit.method; let method = &unit.method;
let socket_host = unit.spoofed_host
.map(|r|r.as_ref())
.unwrap_or(host);
// open socket // open socket
let (mut stream, is_recycled) = connect_socket(unit, host, use_pooled)?; let (mut stream, is_recycled) = connect_socket(unit, socket_host, use_pooled)?;
if is_recycled { if is_recycled {
debug!("sending request (reused connection) {} {}", method, url); debug!("sending request (reused connection) {} {}", method, url);