mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-26 11:43:08 +03:00
Add connect-to option
This commit is contained in:
parent
b9dc82d22c
commit
aa2f1d5b4d
3
integration/tests_ok/connect_to.curl
Normal file
3
integration/tests_ok/connect_to.curl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
curl --connect-to foo.com:80:localhost:8000 --connect-to bar.com:80:localhost:8000 --connect-to baz.com:80:localhost:8000 'http://foo.com/hello'
|
||||||
|
curl --connect-to foo.com:80:localhost:8000 --connect-to bar.com:80:localhost:8000 --connect-to baz.com:80:localhost:8000 'http://bar.com/hello'
|
||||||
|
curl --connect-to foo.com:80:localhost:8000 --connect-to bar.com:80:localhost:8000 --connect-to baz.com:80:localhost:8000 'http://baz.com/hello'
|
14
integration/tests_ok/connect_to.html
Normal file
14
integration/tests_ok/connect_to.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<pre><code class="language-hurl"><span class="hurl-entry"><span class="request"><span class="line"><span class="method">GET</span> <span class="url">http://foo.com/hello</span></span>
|
||||||
|
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="line"><span class="string">`Hello World!`</span></span>
|
||||||
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://bar.com/hello</span></span>
|
||||||
|
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="line"><span class="string">`Hello World!`</span></span>
|
||||||
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://baz.com/hello</span></span>
|
||||||
|
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="line"><span class="string">`Hello World!`</span></span>
|
||||||
|
</span></span></code></pre>
|
13
integration/tests_ok/connect_to.hurl
Normal file
13
integration/tests_ok/connect_to.hurl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
GET http://foo.com/hello
|
||||||
|
HTTP 200
|
||||||
|
`Hello World!`
|
||||||
|
|
||||||
|
|
||||||
|
GET http://bar.com/hello
|
||||||
|
HTTP 200
|
||||||
|
`Hello World!`
|
||||||
|
|
||||||
|
|
||||||
|
GET http://baz.com/hello
|
||||||
|
HTTP 200
|
||||||
|
`Hello World!`
|
1
integration/tests_ok/connect_to.json
Normal file
1
integration/tests_ok/connect_to.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"entries":[{"request":{"method":"GET","url":"http://foo.com/hello"},"response":{"status":200,"body":{"type":"text","value":"Hello World!"}}},{"request":{"method":"GET","url":"http://bar.com/hello"},"response":{"status":200,"body":{"type":"text","value":"Hello World!"}}},{"request":{"method":"GET","url":"http://baz.com/hello"},"response":{"status":200,"body":{"type":"text","value":"Hello World!"}}}]}
|
6
integration/tests_ok/connect_to.options
Normal file
6
integration/tests_ok/connect_to.options
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
--connect-to
|
||||||
|
foo.com:80:localhost:8000
|
||||||
|
--connect-to
|
||||||
|
bar.com:80:localhost:8000
|
||||||
|
--connect-to
|
||||||
|
baz.com:80:localhost:8000
|
1
integration/tests_ok/connect_to.out
Normal file
1
integration/tests_ok/connect_to.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello World!
|
@ -37,6 +37,7 @@ pub struct CliOptions {
|
|||||||
pub client_cert_file: Option<String>,
|
pub client_cert_file: Option<String>,
|
||||||
pub client_key_file: Option<String>,
|
pub client_key_file: Option<String>,
|
||||||
pub color: bool,
|
pub color: bool,
|
||||||
|
pub connects_to: Vec<String>,
|
||||||
pub compressed: bool,
|
pub compressed: bool,
|
||||||
pub connect_timeout: Duration,
|
pub connect_timeout: Duration,
|
||||||
pub cookie_input_file: Option<String>,
|
pub cookie_input_file: Option<String>,
|
||||||
@ -145,6 +146,15 @@ pub fn app(version: &str) -> Command {
|
|||||||
.value_parser(value_parser!(u64))
|
.value_parser(value_parser!(u64))
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::new("connect_to")
|
||||||
|
.long("connect-to")
|
||||||
|
.value_name("HOST1:PORT1:HOST2:PORT2")
|
||||||
|
.help("For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead")
|
||||||
|
.action(ArgAction::Append)
|
||||||
|
.number_of_values(1)
|
||||||
|
.num_args(1)
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::new("cookies_input_file")
|
clap::Arg::new("cookies_input_file")
|
||||||
.short('b')
|
.short('b')
|
||||||
@ -295,12 +305,6 @@ pub fn app(version: &str) -> Command {
|
|||||||
.help("Generate HTML report to DIR")
|
.help("Generate HTML report to DIR")
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
clap::Arg::new("retry")
|
|
||||||
.long("retry")
|
|
||||||
.help("Retry requests on errors")
|
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::new("resolve")
|
clap::Arg::new("resolve")
|
||||||
.long("resolve")
|
.long("resolve")
|
||||||
@ -310,6 +314,12 @@ pub fn app(version: &str) -> Command {
|
|||||||
.number_of_values(1)
|
.number_of_values(1)
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::new("retry")
|
||||||
|
.long("retry")
|
||||||
|
.help("Retry requests on errors")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::new("retry_interval")
|
clap::Arg::new("retry_interval")
|
||||||
.long("retry-interval")
|
.long("retry-interval")
|
||||||
@ -431,6 +441,7 @@ pub fn parse_options(matches: &ArgMatches) -> Result<CliOptions, CliError> {
|
|||||||
let compressed = has_flag(matches, "compressed");
|
let compressed = has_flag(matches, "compressed");
|
||||||
let connect_timeout = get::<u64>(matches, "connect_timeout").unwrap();
|
let connect_timeout = get::<u64>(matches, "connect_timeout").unwrap();
|
||||||
let connect_timeout = Duration::from_secs(connect_timeout);
|
let connect_timeout = Duration::from_secs(connect_timeout);
|
||||||
|
let connects_to = get_strings(matches, "connect_to").unwrap_or_default();
|
||||||
let cookie_input_file = get::<String>(matches, "cookies_input_file");
|
let cookie_input_file = get::<String>(matches, "cookies_input_file");
|
||||||
let cookie_output_file = get::<String>(matches, "cookies_output_file");
|
let cookie_output_file = get::<String>(matches, "cookies_output_file");
|
||||||
let fail_fast = !has_flag(matches, "fail_at_end");
|
let fail_fast = !has_flag(matches, "fail_at_end");
|
||||||
@ -505,6 +516,7 @@ pub fn parse_options(matches: &ArgMatches) -> Result<CliOptions, CliError> {
|
|||||||
color,
|
color,
|
||||||
compressed,
|
compressed,
|
||||||
connect_timeout,
|
connect_timeout,
|
||||||
|
connects_to,
|
||||||
cookie_input_file,
|
cookie_input_file,
|
||||||
cookie_output_file,
|
cookie_output_file,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
|
@ -127,28 +127,28 @@ impl Client {
|
|||||||
// way to get access to the outgoing headers.
|
// way to get access to the outgoing headers.
|
||||||
self.handle.verbose(true).unwrap();
|
self.handle.verbose(true).unwrap();
|
||||||
|
|
||||||
|
if !options.connects_to.is_empty() {
|
||||||
|
let connects = to_list(&options.connects_to);
|
||||||
|
self.handle.connect_to(connects).unwrap();
|
||||||
|
}
|
||||||
if !options.resolves.is_empty() {
|
if !options.resolves.is_empty() {
|
||||||
let resolves = to_list(&options.resolves);
|
let resolves = to_list(&options.resolves);
|
||||||
self.handle.resolve(resolves).unwrap();
|
self.handle.resolve(resolves).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.handle.ssl_verify_host(!options.insecure).unwrap();
|
self.handle.ssl_verify_host(!options.insecure).unwrap();
|
||||||
self.handle.ssl_verify_peer(!options.insecure).unwrap();
|
self.handle.ssl_verify_peer(!options.insecure).unwrap();
|
||||||
if let Some(cacert_file) = options.cacert_file.clone() {
|
if let Some(cacert_file) = options.cacert_file.clone() {
|
||||||
self.handle.cainfo(cacert_file).unwrap();
|
self.handle.cainfo(cacert_file).unwrap();
|
||||||
self.handle.ssl_cert_type("PEM").unwrap();
|
self.handle.ssl_cert_type("PEM").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(client_cert_file) = options.client_cert_file.clone() {
|
if let Some(client_cert_file) = options.client_cert_file.clone() {
|
||||||
self.handle.ssl_cert(client_cert_file).unwrap();
|
self.handle.ssl_cert(client_cert_file).unwrap();
|
||||||
self.handle.ssl_cert_type("PEM").unwrap();
|
self.handle.ssl_cert_type("PEM").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(client_key_file) = options.client_key_file.clone() {
|
if let Some(client_key_file) = options.client_key_file.clone() {
|
||||||
self.handle.ssl_key(client_key_file).unwrap();
|
self.handle.ssl_key(client_key_file).unwrap();
|
||||||
self.handle.ssl_cert_type("PEM").unwrap();
|
self.handle.ssl_cert_type("PEM").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(proxy) = options.proxy.clone() {
|
if let Some(proxy) = options.proxy.clone() {
|
||||||
self.handle.proxy(proxy.as_str()).unwrap();
|
self.handle.proxy(proxy.as_str()).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ pub struct ClientOptions {
|
|||||||
pub cacert_file: Option<String>,
|
pub cacert_file: Option<String>,
|
||||||
pub client_cert_file: Option<String>,
|
pub client_cert_file: Option<String>,
|
||||||
pub client_key_file: Option<String>,
|
pub client_key_file: Option<String>,
|
||||||
|
pub connects_to: Vec<String>,
|
||||||
pub follow_location: bool,
|
pub follow_location: bool,
|
||||||
pub max_redirect: Option<usize>,
|
pub max_redirect: Option<usize>,
|
||||||
pub cookie_input_file: Option<String>,
|
pub cookie_input_file: Option<String>,
|
||||||
@ -50,6 +51,7 @@ impl Default for ClientOptions {
|
|||||||
cacert_file: None,
|
cacert_file: None,
|
||||||
client_cert_file: None,
|
client_cert_file: None,
|
||||||
client_key_file: None,
|
client_key_file: None,
|
||||||
|
connects_to: vec![],
|
||||||
follow_location: false,
|
follow_location: false,
|
||||||
max_redirect: Some(50),
|
max_redirect: Some(50),
|
||||||
cookie_input_file: None,
|
cookie_input_file: None,
|
||||||
@ -77,31 +79,29 @@ impl ClientOptions {
|
|||||||
arguments.push("--cacert".to_string());
|
arguments.push("--cacert".to_string());
|
||||||
arguments.push(cacert_file.clone());
|
arguments.push(cacert_file.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref client_cert_file) = self.client_cert_file {
|
if let Some(ref client_cert_file) = self.client_cert_file {
|
||||||
arguments.push("--cert".to_string());
|
arguments.push("--cert".to_string());
|
||||||
arguments.push(client_cert_file.clone());
|
arguments.push(client_cert_file.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref client_key_file) = self.client_key_file {
|
if let Some(ref client_key_file) = self.client_key_file {
|
||||||
arguments.push("--key".to_string());
|
arguments.push("--key".to_string());
|
||||||
arguments.push(client_key_file.clone());
|
arguments.push(client_key_file.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.compressed {
|
if self.compressed {
|
||||||
arguments.push("--compressed".to_string());
|
arguments.push("--compressed".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.connect_timeout != ClientOptions::default().connect_timeout {
|
if self.connect_timeout != ClientOptions::default().connect_timeout {
|
||||||
arguments.push("--connect-timeout".to_string());
|
arguments.push("--connect-timeout".to_string());
|
||||||
arguments.push(self.connect_timeout.as_secs().to_string());
|
arguments.push(self.connect_timeout.as_secs().to_string());
|
||||||
}
|
}
|
||||||
|
for connect in self.connects_to.iter() {
|
||||||
|
arguments.push("--connect-to".to_string());
|
||||||
|
arguments.push(connect.clone());
|
||||||
|
}
|
||||||
if let Some(ref cookie_file) = self.cookie_input_file {
|
if let Some(ref cookie_file) = self.cookie_input_file {
|
||||||
arguments.push("--cookie".to_string());
|
arguments.push("--cookie".to_string());
|
||||||
arguments.push(cookie_file.clone());
|
arguments.push(cookie_file.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.insecure {
|
if self.insecure {
|
||||||
arguments.push("--insecure".to_string());
|
arguments.push("--insecure".to_string());
|
||||||
}
|
}
|
||||||
@ -153,6 +153,7 @@ mod tests {
|
|||||||
cacert_file: None,
|
cacert_file: None,
|
||||||
client_cert_file: None,
|
client_cert_file: None,
|
||||||
client_key_file: None,
|
client_key_file: None,
|
||||||
|
connects_to: vec!["example.com:443:host-47.example.com:443".to_string()],
|
||||||
follow_location: true,
|
follow_location: true,
|
||||||
max_redirect: Some(10),
|
max_redirect: Some(10),
|
||||||
cookie_input_file: Some("cookie_file".to_string()),
|
cookie_input_file: Some("cookie_file".to_string()),
|
||||||
@ -176,6 +177,8 @@ mod tests {
|
|||||||
"--compressed".to_string(),
|
"--compressed".to_string(),
|
||||||
"--connect-timeout".to_string(),
|
"--connect-timeout".to_string(),
|
||||||
"20".to_string(),
|
"20".to_string(),
|
||||||
|
"--connect-to".to_string(),
|
||||||
|
"example.com:443:host-47.example.com:443".to_string(),
|
||||||
"--cookie".to_string(),
|
"--cookie".to_string(),
|
||||||
"cookie_file".to_string(),
|
"cookie_file".to_string(),
|
||||||
"--insecure".to_string(),
|
"--insecure".to_string(),
|
||||||
|
@ -226,6 +226,7 @@ impl From<&RunnerOptions> for ClientOptions {
|
|||||||
cacert_file: runner_options.cacert_file.clone(),
|
cacert_file: runner_options.cacert_file.clone(),
|
||||||
client_cert_file: runner_options.client_cert_file.clone(),
|
client_cert_file: runner_options.client_cert_file.clone(),
|
||||||
client_key_file: runner_options.client_key_file.clone(),
|
client_key_file: runner_options.client_key_file.clone(),
|
||||||
|
connects_to: runner_options.connects_to.clone(),
|
||||||
follow_location: runner_options.follow_location,
|
follow_location: runner_options.follow_location,
|
||||||
max_redirect: runner_options.max_redirect,
|
max_redirect: runner_options.max_redirect,
|
||||||
cookie_input_file: runner_options.cookie_input_file.clone(),
|
cookie_input_file: runner_options.cookie_input_file.clone(),
|
||||||
|
@ -30,6 +30,7 @@ pub struct RunnerOptions {
|
|||||||
pub client_key_file: Option<String>,
|
pub client_key_file: Option<String>,
|
||||||
pub compressed: bool,
|
pub compressed: bool,
|
||||||
pub connect_timeout: Duration,
|
pub connect_timeout: Duration,
|
||||||
|
pub connects_to: Vec<String>,
|
||||||
pub context_dir: ContextDir,
|
pub context_dir: ContextDir,
|
||||||
pub cookie_input_file: Option<String>,
|
pub cookie_input_file: Option<String>,
|
||||||
pub fail_fast: bool,
|
pub fail_fast: bool,
|
||||||
@ -61,6 +62,7 @@ impl Default for RunnerOptions {
|
|||||||
client_key_file: None,
|
client_key_file: None,
|
||||||
compressed: false,
|
compressed: false,
|
||||||
connect_timeout: Duration::from_secs(300),
|
connect_timeout: Duration::from_secs(300),
|
||||||
|
connects_to: vec![],
|
||||||
context_dir: Default::default(),
|
context_dir: Default::default(),
|
||||||
cookie_input_file: None,
|
cookie_input_file: None,
|
||||||
fail_fast: false,
|
fail_fast: false,
|
||||||
@ -91,6 +93,7 @@ impl RunnerOptions {
|
|||||||
let cacert_file = cli_options.cacert_file.clone();
|
let cacert_file = cli_options.cacert_file.clone();
|
||||||
let client_cert_file = cli_options.client_cert_file.clone();
|
let client_cert_file = cli_options.client_cert_file.clone();
|
||||||
let client_key_file = cli_options.client_key_file.clone();
|
let client_key_file = cli_options.client_key_file.clone();
|
||||||
|
let connects_to = cli_options.connects_to.clone();
|
||||||
let follow_location = cli_options.follow_location;
|
let follow_location = cli_options.follow_location;
|
||||||
let verbosity = match (cli_options.verbose, cli_options.very_verbose) {
|
let verbosity = match (cli_options.verbose, cli_options.very_verbose) {
|
||||||
(true, true) => Some(Verbosity::VeryVerbose),
|
(true, true) => Some(Verbosity::VeryVerbose),
|
||||||
@ -143,6 +146,7 @@ impl RunnerOptions {
|
|||||||
client_key_file,
|
client_key_file,
|
||||||
compressed,
|
compressed,
|
||||||
connect_timeout,
|
connect_timeout,
|
||||||
|
connects_to,
|
||||||
context_dir,
|
context_dir,
|
||||||
cookie_input_file,
|
cookie_input_file,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
|
Loading…
Reference in New Issue
Block a user