mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-26 00:22:10 +03:00
Add --resolve options
This commit is contained in:
parent
93b040e017
commit
38c47501ab
@ -9,6 +9,7 @@ Thanks to
|
||||
[@devnoname120](https://github.com/devnoname120),
|
||||
[@dalejefferson-rnf](https://github.com/dalejefferson-rnf),
|
||||
|
||||
|
||||
Enhancements:
|
||||
|
||||
* Support new one line string [#1041](https://github.com/Orange-OpenSource/hurl/issues/1041)
|
||||
@ -23,6 +24,8 @@ Enhancements:
|
||||
|
||||
* Add GraphQL support [#504](https://github.com/Orange-OpenSource/hurl/issues/504)
|
||||
|
||||
* Add --resolve option [#379](https://github.com/Orange-OpenSource/hurl/issues/379)
|
||||
|
||||
|
||||
Bugs Fixed:
|
||||
|
||||
@ -31,7 +34,6 @@ Bugs Fixed:
|
||||
* Fix querystring key parsing [#1027](https://github.com/Orange-OpenSource/hurl/issues/1027)
|
||||
|
||||
|
||||
|
||||
[1.8.0 (2022-11-02)](https://github.com/Orange-OpenSource/hurl/blob/master/CHANGELOG.md#1.8.0)
|
||||
========================================================================================================================
|
||||
|
||||
|
3
integration/tests_ok/resolve.curl
Normal file
3
integration/tests_ok/resolve.curl
Normal file
@ -0,0 +1,3 @@
|
||||
curl 'http://foo.com:8000/hello' --resolve foo.com:8000:127.0.0.1 --resolve bar.com:8000:127.0.0.1 --resolve baz.com:8000:127.0.0.1
|
||||
curl 'http://bar.com:8000/hello' --resolve foo.com:8000:127.0.0.1 --resolve bar.com:8000:127.0.0.1 --resolve baz.com:8000:127.0.0.1
|
||||
curl 'http://baz.com:8000/hello' --resolve foo.com:8000:127.0.0.1 --resolve bar.com:8000:127.0.0.1 --resolve baz.com:8000:127.0.0.1
|
13
integration/tests_ok/resolve.hurl
Normal file
13
integration/tests_ok/resolve.hurl
Normal file
@ -0,0 +1,13 @@
|
||||
GET http://foo.com:8000/hello
|
||||
HTTP 200
|
||||
`Hello World!`
|
||||
|
||||
|
||||
GET http://bar.com:8000/hello
|
||||
HTTP 200
|
||||
`Hello World!`
|
||||
|
||||
|
||||
GET http://baz.com:8000/hello
|
||||
HTTP 200
|
||||
`Hello World!`
|
6
integration/tests_ok/resolve.options
Normal file
6
integration/tests_ok/resolve.options
Normal file
@ -0,0 +1,6 @@
|
||||
--resolve
|
||||
foo.com:8000:127.0.0.1
|
||||
--resolve
|
||||
bar.com:8000:127.0.0.1
|
||||
--resolve
|
||||
baz.com:8000:127.0.0.1
|
1
integration/tests_ok/resolve.out
Normal file
1
integration/tests_ok/resolve.out
Normal file
@ -0,0 +1 @@
|
||||
Hello World!
|
@ -56,6 +56,7 @@ pub struct CliOptions {
|
||||
pub output: Option<String>,
|
||||
pub output_type: OutputType,
|
||||
pub proxy: Option<String>,
|
||||
pub resolves: Vec<String>,
|
||||
pub retry: bool,
|
||||
pub retry_interval: Duration,
|
||||
pub retry_max_count: Option<usize>,
|
||||
@ -300,6 +301,15 @@ pub fn app(version: &str) -> Command {
|
||||
.help("Retry requests on errors")
|
||||
.action(ArgAction::SetTrue)
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::new("resolve")
|
||||
.long("resolve")
|
||||
.value_name("HOST:PORT:ADDR")
|
||||
.help("Provide a custom address for a specific host and port pair")
|
||||
.action(ArgAction::Append)
|
||||
.number_of_values(1)
|
||||
.num_args(1)
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::new("retry_interval")
|
||||
.long("retry-interval")
|
||||
@ -470,6 +480,7 @@ pub fn parse_options(matches: &ArgMatches) -> Result<CliOptions, CliError> {
|
||||
OutputType::ResponseBody
|
||||
};
|
||||
let proxy = get::<String>(matches, "proxy");
|
||||
let resolves = get_strings(matches, "resolve").unwrap_or_default();
|
||||
let retry = has_flag(matches, "retry");
|
||||
let retry_interval = get::<u64>(matches, "retry_interval").unwrap();
|
||||
let retry_interval = Duration::from_millis(retry_interval);
|
||||
@ -511,6 +522,7 @@ pub fn parse_options(matches: &ArgMatches) -> Result<CliOptions, CliError> {
|
||||
output,
|
||||
output_type,
|
||||
proxy,
|
||||
resolves,
|
||||
retry,
|
||||
retry_interval,
|
||||
retry_max_count,
|
||||
@ -626,11 +638,12 @@ fn match_glob_files(matches: &ArgMatches) -> Result<Vec<String>, CliError> {
|
||||
Ok(filenames)
|
||||
}
|
||||
|
||||
/// Returns a optional value of type `T` from the command line `matches` given the option `name`.
|
||||
/// Returns an optional value of type `T` from the command line `matches` given the option `name`.
|
||||
fn get<T: Clone + Send + Sync + 'static>(matches: &ArgMatches, name: &str) -> Option<T> {
|
||||
matches.get_one::<T>(name).cloned()
|
||||
}
|
||||
|
||||
/// Returns an optional list of `String` from the command line `matches` given the option `name`.
|
||||
pub fn get_strings(matches: &ArgMatches, name: &str) -> Option<Vec<String>> {
|
||||
matches
|
||||
.get_many::<String>(name)
|
||||
|
@ -31,6 +31,7 @@ use super::response::*;
|
||||
use super::{Header, HttpError, Verbosity};
|
||||
use crate::cli::Logger;
|
||||
use crate::http::ContextDir;
|
||||
use curl::easy::List;
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
|
||||
@ -62,14 +63,8 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes an HTTP request, optionally follows redirection and returns a
|
||||
/// Executes an HTTP request `request_spec`, optionally follows redirection and returns a
|
||||
/// list of pair of [`Request`], [`Response`].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `request_spec` - A request specification
|
||||
/// * `options`- Options for this execution
|
||||
/// * `logger`- A logger
|
||||
pub fn execute_with_redirect(
|
||||
&mut self,
|
||||
request_spec: &RequestSpec,
|
||||
@ -117,14 +112,8 @@ impl Client {
|
||||
Ok(calls)
|
||||
}
|
||||
|
||||
/// Executes an HTTP request, without following redirection and returns a
|
||||
/// Executes an HTTP request `request_spec`, without following redirection and returns a
|
||||
/// pair of [`Request`], [`Response`].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `request_spec` - A request specification
|
||||
/// * `options`- Options for this execution
|
||||
/// * `logger`- A logger
|
||||
pub fn execute(
|
||||
&mut self,
|
||||
request_spec: &RequestSpec,
|
||||
@ -137,6 +126,12 @@ impl Client {
|
||||
// to capture HTTP request headers in libcurl `debug_function`. That's the only
|
||||
// way to get access to the outgoing headers.
|
||||
self.handle.verbose(true).unwrap();
|
||||
|
||||
if !options.resolves.is_empty() {
|
||||
let resolves = to_list(&options.resolves);
|
||||
self.handle.resolve(resolves).unwrap();
|
||||
}
|
||||
|
||||
self.handle.ssl_verify_host(!options.insecure).unwrap();
|
||||
self.handle.ssl_verify_peer(!options.insecure).unwrap();
|
||||
if let Some(cacert_file) = options.cacert_file.clone() {
|
||||
@ -710,6 +705,12 @@ pub fn decode_header(data: &[u8]) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_list(items: &[String]) -> List {
|
||||
let mut list = List::new();
|
||||
items.iter().for_each(|l| list.append(l).unwrap());
|
||||
list
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -29,6 +29,7 @@ pub struct ClientOptions {
|
||||
pub no_proxy: Option<String>,
|
||||
pub verbosity: Option<Verbosity>,
|
||||
pub insecure: bool,
|
||||
pub resolves: Vec<String>,
|
||||
pub retry_max_count: Option<usize>,
|
||||
pub timeout: Duration,
|
||||
pub connect_timeout: Duration,
|
||||
@ -56,6 +57,7 @@ impl Default for ClientOptions {
|
||||
no_proxy: None,
|
||||
verbosity: None,
|
||||
insecure: false,
|
||||
resolves: vec![],
|
||||
retry_max_count: Some(10),
|
||||
timeout: Duration::from_secs(300),
|
||||
connect_timeout: Duration::from_secs(300),
|
||||
@ -117,6 +119,10 @@ impl ClientOptions {
|
||||
arguments.push("--proxy".to_string());
|
||||
arguments.push(format!("'{}'", proxy));
|
||||
}
|
||||
for resolve in self.resolves.iter() {
|
||||
arguments.push("--resolve".to_string());
|
||||
arguments.push(resolve.clone());
|
||||
}
|
||||
if self.timeout != ClientOptions::default().timeout {
|
||||
arguments.push("--timeout".to_string());
|
||||
arguments.push(self.timeout.as_secs().to_string());
|
||||
@ -153,6 +159,10 @@ mod tests {
|
||||
no_proxy: None,
|
||||
verbosity: None,
|
||||
insecure: true,
|
||||
resolves: vec![
|
||||
"foo.com:80:192.168.0.1".to_string(),
|
||||
"bar.com:443:127.0.0.1".to_string()
|
||||
],
|
||||
retry_max_count: Some(10),
|
||||
timeout: Duration::from_secs(10),
|
||||
connect_timeout: Duration::from_secs(20),
|
||||
@ -173,6 +183,10 @@ mod tests {
|
||||
"10".to_string(),
|
||||
"--proxy".to_string(),
|
||||
"'localhost:3128'".to_string(),
|
||||
"--resolve".to_string(),
|
||||
"foo.com:80:192.168.0.1".to_string(),
|
||||
"--resolve".to_string(),
|
||||
"bar.com:443:127.0.0.1".to_string(),
|
||||
"--timeout".to_string(),
|
||||
"10".to_string(),
|
||||
"--user".to_string(),
|
||||
|
@ -207,6 +207,7 @@ impl From<&RunnerOptions> for ClientOptions {
|
||||
Verbosity::VeryVerbose => http::Verbosity::VeryVerbose,
|
||||
}),
|
||||
insecure: runner_options.insecure,
|
||||
resolves: runner_options.resolves.clone(),
|
||||
retry_max_count: runner_options.retry_max_count,
|
||||
timeout: runner_options.timeout,
|
||||
connect_timeout: runner_options.connect_timeout,
|
||||
|
@ -41,6 +41,7 @@ pub struct RunnerOptions {
|
||||
pub post_entry: Option<fn() -> bool>,
|
||||
pub pre_entry: Option<fn(Entry) -> bool>,
|
||||
pub proxy: Option<String>,
|
||||
pub resolves: Vec<String>,
|
||||
pub retry: bool,
|
||||
pub retry_interval: Duration,
|
||||
pub retry_max_count: Option<usize>,
|
||||
@ -71,6 +72,7 @@ impl Default for RunnerOptions {
|
||||
post_entry: None,
|
||||
pre_entry: None,
|
||||
proxy: None,
|
||||
resolves: vec![],
|
||||
retry: false,
|
||||
retry_interval: Duration::from_millis(1000),
|
||||
retry_max_count: Some(10),
|
||||
@ -129,6 +131,7 @@ impl RunnerOptions {
|
||||
};
|
||||
let fail_fast = cli_options.fail_fast;
|
||||
let to_entry = cli_options.to_entry;
|
||||
let resolves = cli_options.resolves.clone();
|
||||
let retry = cli_options.retry;
|
||||
let retry_interval = cli_options.retry_interval;
|
||||
let retry_max_count = cli_options.retry_max_count;
|
||||
@ -151,6 +154,7 @@ impl RunnerOptions {
|
||||
post_entry,
|
||||
pre_entry,
|
||||
proxy,
|
||||
resolves,
|
||||
retry,
|
||||
retry_interval,
|
||||
retry_max_count,
|
||||
|
Loading…
Reference in New Issue
Block a user