diff --git a/packages/hurl/clippy.toml b/packages/hurl/clippy.toml new file mode 100644 index 00000000000..dcec9d87f5e --- /dev/null +++ b/packages/hurl/clippy.toml @@ -0,0 +1 @@ +too-many-arguments-threshold = 8 \ No newline at end of file diff --git a/packages/hurl/src/http/client.rs b/packages/hurl/src/http/client.rs index ceb95066522..33d3b2167cc 100644 --- a/packages/hurl/src/http/client.rs +++ b/packages/hurl/src/http/client.rs @@ -15,6 +15,7 @@ * limitations under the License. * */ + use std::io::Read; use std::str; @@ -34,26 +35,23 @@ use url::Url; #[derive(Debug)] pub struct Client { - pub options: ClientOptions, pub handle: Box, pub redirect_count: usize, // Unfortunately, follow-location feature from libcurl can not be used // libcurl returns a single list of headers for the 2 responses - // hurl needs to keep everything + // Hurl needs to keep everything. } impl Client { + /// Inits HTTP hurl client. /// - /// Init HTTP hurl client + /// # Arguments /// - pub fn init(options: ClientOptions) -> Client { + /// * `options`- HTTP client's options + pub fn init(options: &ClientOptions) -> Client { let mut h = easy::Easy::new(); - // Set handle attributes - // that are not affected by reset - - // Activate cookie storage - // with or without persistence (empty string) + // Activate cookie storage with or without persistence (empty string) h.cookie_file( options .cookie_input_file @@ -64,30 +62,32 @@ impl Client { .unwrap(); Client { - options, handle: Box::new(h), redirect_count: 0, } } - /// Execute an HTTP request and returns a list + /// Executes an HTTP request and returns a list of request / response pair. /// - /// # Arguments + /// Any redirection is followed if necessary. /// - /// * request - A request specification + /// # Arguments /// + /// * `request` - A request specification + /// * `options`- HTTP client's options pub fn execute_with_redirect( &mut self, request: &RequestSpec, + options: &ClientOptions, ) -> Result, HttpError> { let mut calls = vec![]; let mut request_spec = request.clone(); self.redirect_count = 0; loop { - let (request, response) = self.execute(&request_spec)?; + let (request, response) = self.execute(&request_spec, options)?; calls.push((request, response.clone())); - if let Some(url) = self.get_follow_location(response.clone()) { + if let Some(url) = self.get_follow_location(response.clone(), options) { request_spec = RequestSpec { method: Method::Get, url, @@ -101,7 +101,7 @@ impl Client { }; self.redirect_count += 1; - if let Some(max_redirect) = self.options.max_redirect { + if let Some(max_redirect) = options.max_redirect { if self.redirect_count > max_redirect { return Err(HttpError::TooManyRedirect); } @@ -113,33 +113,41 @@ impl Client { Ok(calls) } + /// Executes an HTTP request and returns a request / response pair. /// - /// Execute an http request + /// Contrary to `execute_with_redirect` method, no redirection is followed. /// - pub fn execute(&mut self, request: &RequestSpec) -> Result<(Request, Response), HttpError> { - // set handle attributes - // that have not been set or reset + /// # Arguments + /// + /// * `request` - A request specification + /// * `options`- HTTP client's options + pub fn execute( + &mut self, + request: &RequestSpec, + options: &ClientOptions, + ) -> Result<(Request, Response), HttpError> { + // Set handle attributes that have not been set or reset. // We force libcurl verbose mode regardless of Hurl verbose option to be able // 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(); - self.handle.ssl_verify_host(!self.options.insecure).unwrap(); - self.handle.ssl_verify_peer(!self.options.insecure).unwrap(); - if let Some(cacert_file) = self.options.cacert_file.clone() { + 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() { self.handle.cainfo(cacert_file).unwrap(); self.handle.ssl_cert_type("PEM").unwrap(); } - if let Some(proxy) = self.options.proxy.clone() { + if let Some(proxy) = options.proxy.clone() { self.handle.proxy(proxy.as_str()).unwrap(); } - if let Some(s) = self.options.no_proxy.clone() { + if let Some(s) = options.no_proxy.clone() { self.handle.noproxy(s.as_str()).unwrap(); } - self.handle.timeout(self.options.timeout).unwrap(); + self.handle.timeout(options.timeout).unwrap(); self.handle - .connect_timeout(self.options.connect_timeout) + .connect_timeout(options.connect_timeout) .unwrap(); let url = self.generate_url(&request.url, &request.querystring); @@ -154,9 +162,9 @@ impl Client { let mut data: &[u8] = bytes.as_ref(); self.set_body(data); - self.set_headers(request); + self.set_headers(request, options); - let verbose = self.options.verbosity != None; + let verbose = options.verbosity != None; let mut request_headers: Vec
= vec![]; let start = Instant::now(); @@ -266,16 +274,14 @@ impl Client { duration, }; - if self.options.verbosity == Some(Verbosity::VeryVerbose) { + if options.verbosity == Some(Verbosity::VeryVerbose) { response.log_body(); } Ok((request, response)) } - /// - /// generate url - /// + /// Generates url. fn generate_url(&mut self, url: &str, params: &[Param]) -> String { let url = if params.is_empty() { url.to_string() @@ -287,15 +293,13 @@ impl Client { } else { format!("{}?", url) }; - let s = self.encode_params(params); + let s = self.url_encode_params(params); format!("{}{}", url, s) }; url } - /// - /// set method - /// + /// Set method. fn set_method(&mut self, method: &Method) { match method { Method::Get => self.handle.custom_request("GET").unwrap(), @@ -310,10 +314,8 @@ impl Client { } } - /// - /// set request headers - /// - fn set_headers(&mut self, request: &RequestSpec) { + /// Set request headers. + fn set_headers(&mut self, request: &RequestSpec, options: &ClientOptions) { let mut list = easy::List::new(); for header in &request.headers { @@ -335,7 +337,7 @@ impl Client { } if request.get_header_values("User-Agent").is_empty() { - let user_agent = match self.options.user_agent { + let user_agent = match options.user_agent { Some(ref u) => u.clone(), None => format!("hurl/{}", clap::crate_version!()), }; @@ -343,23 +345,21 @@ impl Client { .unwrap(); } - if let Some(ref user) = self.options.user { + if let Some(ref user) = options.user { let authorization = base64::encode(user.as_bytes()); if request.get_header_values("Authorization").is_empty() { list.append(format!("Authorization: Basic {}", authorization).as_str()) .unwrap(); } } - if self.options.compressed && request.get_header_values("Accept-Encoding").is_empty() { + if options.compressed && request.get_header_values("Accept-Encoding").is_empty() { list.append("Accept-Encoding: gzip, deflate, br").unwrap(); } self.handle.http_headers(list).unwrap(); } - /// - /// set request cookies - /// + /// Set request cookies. fn set_cookies(&mut self, cookies: &[RequestCookie]) { let s = cookies .iter() @@ -371,20 +371,16 @@ impl Client { } } - /// - /// set form - /// + /// Set form. fn set_form(&mut self, params: &[Param]) { if !params.is_empty() { - let s = self.encode_params(params); + let s = self.url_encode_params(params); self.handle.post_fields_copy(s.as_str().as_bytes()).unwrap(); //self.handle.write_function(sink); } } - /// - /// set form - /// + /// Set multipart form params. fn set_multipart(&mut self, params: &[MultipartParam]) { if !params.is_empty() { let mut form = easy::Form::new(); @@ -410,9 +406,7 @@ impl Client { } } - /// - /// set body - /// + /// Set request body. fn set_body(&mut self, data: &[u8]) { if !data.is_empty() { self.handle.post(true).unwrap(); @@ -420,10 +414,8 @@ impl Client { } } - /// - /// encode parameters - /// - fn encode_params(&mut self, params: &[Param]) -> String { + /// Url encodes request parameters. + fn url_encode_params(&mut self, params: &[Param]) -> String { params .iter() .map(|p| { @@ -434,9 +426,7 @@ impl Client { .join("&") } - /// - /// parse response version - /// + /// Parses response version. fn parse_response_version(&mut self, line: String) -> Result { if line.starts_with("HTTP/1.0") { Ok(Version::Http10) @@ -449,9 +439,7 @@ impl Client { } } - /// - /// parse headers from libcurl responses - /// + /// Parses headers from libcurl responses. fn parse_response_headers(&mut self, lines: &[String]) -> Vec
{ let mut headers: Vec
= vec![]; for line in lines { @@ -462,15 +450,18 @@ impl Client { headers } + /// Retrieves an optional location to follow. /// - /// retrieve an optional location to follow /// You need: /// 1. the option follow_location set to true /// 2. a 3xx response code /// 3. a header Location - /// - fn get_follow_location(&mut self, response: Response) -> Option { - if !self.options.follow_location { + fn get_follow_location( + &mut self, + response: Response, + options: &ClientOptions, + ) -> Option { + if !options.follow_location { return None; } let response_code = response.status; @@ -489,9 +480,7 @@ impl Client { } } - /// - /// get cookie storage - /// + /// Get cookie storage. pub fn get_cookie_storage(&mut self) -> Vec { let list = self.handle.cookies().unwrap(); let mut cookies = vec![]; @@ -506,11 +495,9 @@ impl Client { cookies } - /// - /// Add cookie to Cookiejar - /// - pub fn add_cookie(&mut self, cookie: Cookie) { - if self.options.verbosity != None { + /// Adds cookie to cookie jar. + pub fn add_cookie(&mut self, cookie: Cookie, options: &ClientOptions) { + if options.verbosity != None { eprintln!("* add to cookie store: {}", cookie); } self.handle @@ -518,22 +505,22 @@ impl Client { .unwrap(); } - /// - /// Clear cookie storage - /// - pub fn clear_cookie_storage(&mut self) { - if self.options.verbosity != None { + /// Clears cookie jar. + pub fn clear_cookie_storage(&mut self, options: &ClientOptions) { + if options.verbosity != None { eprintln!("* clear cookie storage"); } self.handle.cookie_list("ALL").unwrap(); } - /// - /// return curl command-line for the http request run by the client - /// - pub fn curl_command_line(&mut self, http_request: &RequestSpec) -> String { + /// Returns curl command-line for the HTTP request run by the client. + pub fn curl_command_line( + &mut self, + http_request: &RequestSpec, + options: &ClientOptions, + ) -> String { let mut arguments = vec!["curl".to_string()]; - let context_dir = &self.options.context_dir; + let context_dir = &options.context_dir; arguments.append(&mut http_request.curl_args(context_dir)); let cookies = all_cookies(self.get_cookie_storage(), http_request); @@ -548,14 +535,12 @@ impl Client { .join("; ") )); } - arguments.append(&mut self.options.curl_args()); + arguments.append(&mut options.curl_args()); arguments.join(" ") } } -/// -/// return cookies from both cookies from the cookie storage and the request -/// +/// Returns cookies from both the cookie storage and the request. pub fn all_cookies(cookie_storage: Vec, request: &RequestSpec) -> Vec { let mut cookies = request.cookies.clone(); cookies.append( @@ -572,11 +557,9 @@ pub fn all_cookies(cookie_storage: Vec, request: &RequestSpec) -> Vec bool { - // is it possible to do it with libcurl? + // FIXME: is it possible to do it with libcurl? let url = match Url::parse(url) { Ok(url) => url, Err(_) => return false, @@ -594,10 +577,8 @@ pub fn match_cookie(cookie: &Cookie, url: &str) -> bool { } impl Header { - /// - /// Parse an http header line received from the server - /// It does not panic. Just return none if it can not be parsed - /// + /// Parses an HTTP header line received from the server. + /// It does not panic. Just returns [`None`] if it can not be parsed. pub fn parse(line: String) -> Option
{ match line.find(':') { Some(index) => { @@ -612,9 +593,7 @@ impl Header { } } -/// -/// Split an array of bytes into http lines (\r\n separator) -/// +/// Splits an array of bytes into HTTP lines (\r\n separator). fn split_lines(data: &[u8]) -> Vec { let mut lines = vec![]; let mut start = 0; @@ -633,9 +612,7 @@ fn split_lines(data: &[u8]) -> Vec { lines } -/// -/// Decode optionally header value as text with utf8 or iso-8859-1 encoding -/// +/// Decodes optionally header value as text with utf8 or iso-8859-1 encoding. pub fn decode_header(data: &[u8]) -> Option { match str::from_utf8(data) { Ok(s) => Some(s.to_string()), diff --git a/packages/hurl/src/main.rs b/packages/hurl/src/main.rs index cdbfb340375..1a1d0500808 100644 --- a/packages/hurl/src/main.rs +++ b/packages/hurl/src/main.rs @@ -183,7 +183,7 @@ fn execute( }; let context_dir = ContextDir::new(current_dir, file_root); - let options = http::ClientOptions { + let client_options = http::ClientOptions { cacert_file, follow_location, max_redirect, @@ -200,7 +200,7 @@ fn execute( context_dir: context_dir.clone(), }; - let mut client = http::Client::init(options); + let mut client = http::Client::init(&client_options); let pre_entry = if cli_options.interactive { cli::interactive::pre_entry @@ -217,7 +217,7 @@ fn execute( let to_entry = cli_options.to_entry; let ignore_asserts = cli_options.ignore_asserts; let very_verbose = cli_options.very_verbose; - let options = RunnerOptions { + let runner_options = RunnerOptions { fail_fast, variables, to_entry, @@ -229,9 +229,10 @@ fn execute( }; let result = runner::run( hurl_file, - &mut client, filename, - &options, + &mut client, + &client_options, + &runner_options, &log_verbose, &log_error_message, &log_runner_error, diff --git a/packages/hurl/src/runner/entry.rs b/packages/hurl/src/runner/entry.rs index 86e608e0909..e518809c6b8 100644 --- a/packages/hurl/src/runner/entry.rs +++ b/packages/hurl/src/runner/entry.rs @@ -18,6 +18,7 @@ use std::collections::HashMap; use crate::http; +use crate::http::ClientOptions; use hurl_core::ast::*; use super::core::*; @@ -27,35 +28,35 @@ use super::response::{eval_asserts, eval_captures}; use super::value::Value; use crate::runner::request::{cookie_storage_clear, cookie_storage_set}; -/// Run an entry with the hurl http client -/// Return one or more EntryResults (if following redirect) +/// Runs an entry with the hurl HTTP client. /// -/// # Examples +/// Returns one or more EntryResults (if following redirect) /// -/// ``` -/// use hurl::http; -/// use hurl::runner; +/// # Arguments /// -/// // Create an http client -//// let client = http::client::Client::init(http::client::ClientOptions { -//// noproxy_hosts: vec![], -//// insecure: false, -//// redirect: http::client::Redirect::None, -//// http_proxy: None, -//// https_proxy: None, -//// all_proxy: None -//// }); -/// ``` +/// * `entry` - An entry to be executed +/// * `http_client` - The HTTP client +/// * `client_options` - HTTP client's options +/// * `entry_index` - Entry's index (1 based) +/// * `variables` - Map of variables for templated values +/// * `log_verbose` - Log info function +/// * `log_error_message`- Log error function +/// * `runner_options` - Runner's options pub fn run( entry: Entry, - http_client: &mut http::Client, entry_index: usize, + http_client: &mut http::Client, + client_options: &ClientOptions, variables: &mut HashMap, + ignore_asserts: bool, log_verbose: &impl Fn(&str), log_error_message: &impl Fn(bool, &str), - options: &RunnerOptions, ) -> Vec { - let http_request = match eval_request(entry.request.clone(), variables, &options.context_dir) { + let http_request = match eval_request( + entry.request.clone(), + variables, + &client_options.context_dir, + ) { Ok(r) => r, Err(error) => { return vec![EntryResult { @@ -77,7 +78,7 @@ pub fn run( use std::str::FromStr; if let Some(s) = cookie_storage_set(entry.request.clone()) { if let Ok(cookie) = http::Cookie::from_str(s.as_str()) { - http_client.add_cookie(cookie); + http_client.add_cookie(cookie, client_options); } else { log_error_message( true, @@ -86,7 +87,7 @@ pub fn run( } } if cookie_storage_clear(entry.request.clone()) { - http_client.clear_cookie_storage(); + http_client.clear_cookie_storage(client_options); } log_verbose(""); @@ -99,12 +100,12 @@ pub fn run( log_verbose( format!( "Request can be run with the following curl command:\n* {}\n*", - http_client.curl_command_line(&http_request) + http_client.curl_command_line(&http_request, client_options) ) .as_str(), ); - let calls = match http_client.execute_with_redirect(&http_request) { + let calls = match http_client.execute_with_redirect(&http_request, client_options) { Ok(calls) => calls, Err(http_error) => { let runner_error = RunnerError::from(http_error); @@ -155,7 +156,7 @@ pub fn run( for capture_result in captures.clone() { variables.insert(capture_result.name, capture_result.value); } - asserts = if options.ignore_asserts { + asserts = if ignore_asserts { vec![] } else { match entry.response.clone() { @@ -164,7 +165,7 @@ pub fn run( response, variables, http_response.clone(), - &options.context_dir, + &client_options.context_dir, ), } }; diff --git a/packages/hurl/src/runner/hurl_file.rs b/packages/hurl/src/runner/hurl_file.rs index 0d7efc477a6..89e22cf91d4 100644 --- a/packages/hurl/src/runner/hurl_file.rs +++ b/packages/hurl/src/runner/hurl_file.rs @@ -19,6 +19,7 @@ use std::collections::HashMap; use std::time::Instant; use crate::http; +use crate::http::ClientOptions; use hurl_core::ast::*; use super::core::*; @@ -43,18 +44,18 @@ use super::entry; /// "#; /// let hurl_file = parser::parse_hurl_file(s).unwrap(); /// -/// // create loggers (function pointer or closure) +/// // Create loggers (function pointer or closure) /// fn log_verbose(message: &str) { eprintln!("* {}", message); } /// fn log_error_message(_warning:bool, message: &str) { eprintln!("{}", message); } /// fn log_error(error: &runner::Error, _warning: bool) { eprintln!("* {:#?}", error); } /// /// // Create an http client -/// let options = http::ClientOptions::default(); -/// let mut client = http::Client::init(options); +/// let client_options = http::ClientOptions::default(); +/// let mut client = http::Client::init(&client_options); /// /// // Define runner options /// let variables = std::collections::HashMap::new(); -/// let options = runner::RunnerOptions { +/// let runner_options = runner::RunnerOptions { /// fail_fast: false, /// variables, /// to_entry: None, @@ -68,9 +69,10 @@ use super::entry; /// // Run the hurl file /// let hurl_results = runner::run( /// hurl_file, -/// &mut client, /// filename, -/// &options, +/// &mut client, +/// &client_options, +/// &runner_options, /// &log_verbose, /// &log_error_message, /// &log_error, @@ -81,9 +83,10 @@ use super::entry; /// pub fn run( hurl_file: HurlFile, - http_client: &mut http::Client, filename: &str, - options: &RunnerOptions, + http_client: &mut http::Client, + client_options: &ClientOptions, + runner_options: &RunnerOptions, log_verbose: &impl Fn(&str), log_error_message: &impl Fn(bool, &str), log_error: &impl Fn(&Error, bool), @@ -91,11 +94,11 @@ pub fn run( let mut entries = vec![]; let mut variables = HashMap::default(); - for (key, value) in options.variables.clone() { + for (key, value) in runner_options.variables.clone() { variables.insert(key.to_string(), value); } - let n = if let Some(to_entry) = options.to_entry { + let n = if let Some(to_entry) = runner_options.to_entry { to_entry } else { hurl_file.entries.len() @@ -110,19 +113,20 @@ pub fn run( .enumerate() .collect::>() { - let exit = (options.pre_entry)(entry.clone()); + let exit = (runner_options.pre_entry)(entry.clone()); if exit { break; } let entry_results = entry::run( entry, - http_client, entry_index, + http_client, + client_options, &mut variables, + runner_options.ignore_asserts, &log_verbose, &log_error_message, - options, ); for entry_result in entry_results.clone() { @@ -131,8 +135,8 @@ pub fn run( } entries.push(entry_result.clone()); } - let exit = (options.post_entry)(); - if exit || (options.fail_fast && !entry_results.last().unwrap().errors.is_empty()) { + let exit = (runner_options.post_entry)(); + if exit || (runner_options.fail_fast && !entry_results.last().unwrap().errors.is_empty()) { break; } } diff --git a/packages/hurl/tests/libcurl.rs b/packages/hurl/tests/libcurl.rs index 1be7862ce54..fa312ef5007 100644 --- a/packages/hurl/tests/libcurl.rs +++ b/packages/hurl/tests/libcurl.rs @@ -30,7 +30,7 @@ pub fn new_header(name: &str, value: &str) -> Header { fn default_client() -> Client { let options = ClientOptions::default(); - Client::init(options) + Client::init(&options) } fn default_get_request(url: String) -> RequestSpec { @@ -47,18 +47,19 @@ fn default_get_request(url: String) -> RequestSpec { } } -// region basic +// region Basic #[test] fn test_hello() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = default_get_request("http://localhost:8000/hello".to_string()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/hello'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "GET".to_string()); assert_eq!(request.url, "http://localhost:8000/hello".to_string()); assert_eq!(request.headers.len(), 3); @@ -89,11 +90,12 @@ fn test_hello() { // endregion -// region http method +// region HTTP method #[test] fn test_put() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Put, url: "http://localhost:8000/put".to_string(), @@ -106,11 +108,11 @@ fn test_put() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/put' -X PUT".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "PUT".to_string()); assert_eq!(request.url, "http://localhost:8000/put".to_string()); assert!(request.headers.contains(&Header { @@ -129,6 +131,7 @@ fn test_put() { #[test] fn test_patch() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Patch, url: "http://localhost:8000/patch/file.txt".to_string(), @@ -154,11 +157,11 @@ fn test_patch() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/patch/file.txt' -X PATCH -H 'Host: www.example.com' -H 'Content-Type: application/example' -H 'If-Match: \"e0023aa4e\"'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "PATCH".to_string()); assert_eq!( request.url, @@ -179,11 +182,12 @@ fn test_patch() { // endregion -// region headers +// region Headers #[test] fn test_custom_headers() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Get, url: "http://localhost:8000/custom-headers".to_string(), @@ -201,13 +205,13 @@ fn test_custom_headers() { body: Body::Binary(vec![]), content_type: None, }; - assert!(client.options.curl_args().is_empty()); + assert!(options.curl_args().is_empty()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/custom-headers' -H 'Fruit: Raspberry' -H 'Fruit: Apple' -H 'Fruit: Banana' -H 'Fruit: Grape' -H 'Color: Green'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "GET".to_string()); assert_eq!( request.url, @@ -223,11 +227,12 @@ fn test_custom_headers() { // endregion -// region querystrings +// region Querystrings #[test] fn test_querystring_params() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Get, url: "http://localhost:8000/querystring-params".to_string(), @@ -257,10 +262,10 @@ fn test_querystring_params() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/querystring-params?param1=value1¶m2=¶m3=a%3Db¶m4=1%2C2%2C3'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "GET".to_string()); assert_eq!(request.url, "http://localhost:8000/querystring-params?param1=value1¶m2=¶m3=a%3Db¶m4=1%2C2%2C3".to_string()); assert_eq!(request.headers.len(), 3); @@ -271,11 +276,12 @@ fn test_querystring_params() { // endregion -// region form params +// region Form params #[test] fn test_form_params() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Post, url: "http://localhost:8000/form-params".to_string(), @@ -313,11 +319,11 @@ fn test_form_params() { content_type: Some("application/x-www-form-urlencoded".to_string()), }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/form-params' --data 'param1=value1' --data 'param2=' --data 'param3=a%3Db' --data 'param4=a%253db' --data 'values[0]=0' --data 'values[1]=1'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "POST".to_string()); assert_eq!(request.url, "http://localhost:8000/form-params".to_string()); assert!(request.headers.contains(&Header { @@ -330,7 +336,7 @@ fn test_form_params() { // make sure you can reuse client for other request let request = default_get_request("http://localhost:8000/hello".to_string()); - let (request, response) = client.execute(&request).unwrap(); + let (request, response) = client.execute(&request, &options).unwrap(); assert_eq!(request.method, "GET".to_string()); assert_eq!(request.url, "http://localhost:8000/hello".to_string()); assert_eq!(request.headers.len(), 3); @@ -340,14 +346,14 @@ fn test_form_params() { // endregion -// region redirect +// region Redirect #[test] fn test_redirect() { let request_spec = default_get_request("http://localhost:8000/redirect".to_string()); - + let options = ClientOptions::default(); let mut client = default_client(); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "GET".to_string()); assert_eq!(request.url, "http://localhost:8000/redirect".to_string()); assert_eq!(request.headers.len(), 3); @@ -368,14 +374,14 @@ fn test_follow_location() { follow_location: true, ..Default::default() }; - let mut client = Client::init(options); - assert_eq!(client.options.curl_args(), vec!["-L".to_string(),]); + let mut client = Client::init(&options); + assert_eq!(options.curl_args(), vec!["-L".to_string(),]); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/redirect' -L".to_string() ); - let calls = client.execute_with_redirect(&request_spec).unwrap(); + let calls = client.execute_with_redirect(&request_spec, &options).unwrap(); assert_eq!(calls.len(), 2); let (request1, response1) = calls.get(0).unwrap(); @@ -398,7 +404,7 @@ fn test_follow_location() { // make sure that the redirect count is reset to 0 let request = default_get_request("http://localhost:8000/hello".to_string()); - let calls = client.execute_with_redirect(&request).unwrap(); + let calls = client.execute_with_redirect(&request, &options).unwrap(); let (_, response) = calls.get(0).unwrap(); assert_eq!(response.status, 200); assert_eq!(response.body, b"Hello World!".to_vec()); @@ -412,22 +418,22 @@ fn test_max_redirect() { max_redirect: Some(10), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("http://localhost:8000/redirect/15".to_string()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/redirect/15' -L --max-redirs 10".to_string() ); - let error = client.execute_with_redirect(&request_spec).err().unwrap(); + let error = client.execute_with_redirect(&request_spec, &options).err().unwrap(); assert_eq!(error, HttpError::TooManyRedirect); let request_spec = default_get_request("http://localhost:8000/redirect/8".to_string()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/redirect/8' -L --max-redirs 10".to_string() ); - let calls = client.execute_with_redirect(&request_spec).unwrap(); + let calls = client.execute_with_redirect(&request_spec, &options).unwrap(); let (request, response) = calls.last().unwrap(); assert_eq!(request.url, "http://localhost:8000/redirect/0".to_string()); assert_eq!(response.status, 200); @@ -436,11 +442,12 @@ fn test_max_redirect() { // endregion -// region multipart +// region Multipart #[test] fn test_multipart_form_data() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Post, url: "http://localhost:8000/multipart-form-data".to_string(), @@ -476,11 +483,11 @@ fn test_multipart_form_data() { content_type: Some("multipart/form-data".to_string()), }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/multipart-form-data' -F 'key1=value1' -F 'upload1=@data.txt;type=text/plain' -F 'upload2=@data.html;type=text/html' -F 'upload3=@data.txt;type=text/html'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Content-Length".to_string(), value: "627".to_string(), @@ -490,7 +497,7 @@ fn test_multipart_form_data() { // make sure you can reuse client for other request let request_spec = default_get_request("http://localhost:8000/hello".to_string()); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.method, "GET".to_string()); assert_eq!(response.status, 200); assert_eq!(response.body, b"Hello World!".to_vec()); @@ -498,11 +505,12 @@ fn test_multipart_form_data() { // endregion -// region http body +// region HTTP body #[test] fn test_post_bytes() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Post, url: "http://localhost:8000/post-base64".to_string(), @@ -515,10 +523,10 @@ fn test_post_bytes() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/post-base64' -H 'Content-Type: application/octet-stream' --data $'\\x48\\x65\\x6c\\x6c\\x6f\\x20\\x57\\x6f\\x72\\x6c\\x64\\x21'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Content-Length".to_string(), value: "12".to_string(), @@ -533,6 +541,7 @@ fn test_post_bytes() { #[test] fn test_expect() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Post, url: "http://localhost:8000/expect".to_string(), @@ -548,11 +557,11 @@ fn test_expect() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/expect' -H 'Expect: 100-continue' -H 'Content-Type:' --data 'data'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Expect".to_string(), value: "100-continue".to_string(), @@ -568,7 +577,7 @@ fn test_basic_authentication() { user: Some("bob@email.com:secret".to_string()), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = RequestSpec { method: Method::Get, url: "http://localhost:8000/basic-authentication".to_string(), @@ -581,11 +590,11 @@ fn test_basic_authentication() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/basic-authentication' --user 'bob@email.com:secret'" .to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Authorization".to_string(), value: "Basic Ym9iQGVtYWlsLmNvbTpzZWNyZXQ=".to_string(), @@ -610,7 +619,7 @@ fn test_basic_authentication() { request_spec.curl_args(&ContextDir::default()), vec!["'http://bob%40email.com:secret@localhost:8000/basic-authentication'".to_string()] ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Authorization".to_string(), value: "Basic Ym9iQGVtYWlsLmNvbTpzZWNyZXQ=".to_string(), @@ -626,19 +635,20 @@ fn test_cacert() { cacert_file: Some("tests/cert.pem".to_string()), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("https://localhost:8001/hello".to_string()); - let (_, response) = client.execute(&request_spec).unwrap(); + let (_, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(response.status, 200); } -// region error +// region Error #[test] fn test_error_could_not_resolve_host() { let mut client = default_client(); + let options = ClientOptions::default(); let request = default_get_request("http://unknown".to_string()); - let error = client.execute(&request).err().unwrap(); + let error = client.execute(&request, &options).err().unwrap(); assert!(matches!(error, HttpError::Libcurl { .. })); if let HttpError::Libcurl { code, @@ -655,8 +665,9 @@ fn test_error_could_not_resolve_host() { #[test] fn test_error_fail_to_connect() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = default_get_request("http://localhost:9999".to_string()); - let error = client.execute(&request_spec).err().unwrap(); + let error = client.execute(&request_spec, &options).err().unwrap(); assert!(matches!(error, HttpError::Libcurl { .. })); if let HttpError::Libcurl { code, @@ -673,9 +684,9 @@ fn test_error_fail_to_connect() { proxy: Some("localhost:9999".to_string()), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request = default_get_request("http://localhost:8000/hello".to_string()); - let error = client.execute(&request).err().unwrap(); + let error = client.execute(&request, &options).err().unwrap(); assert!(matches!(error, HttpError::Libcurl { .. })); if let HttpError::Libcurl { code, @@ -696,9 +707,9 @@ fn test_error_could_not_resolve_proxy_name() { proxy: Some("unknown".to_string()), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("http://localhost:8000/hello".to_string()); - let error = client.execute(&request_spec).err().unwrap(); + let error = client.execute(&request_spec, &options).err().unwrap(); assert!(matches!(error, HttpError::Libcurl { .. })); if let HttpError::Libcurl { code, @@ -715,9 +726,9 @@ fn test_error_could_not_resolve_proxy_name() { #[test] fn test_error_ssl() { let options = ClientOptions::default(); - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("https://localhost:8001/hello".to_string()); - let error = client.execute(&request_spec).err().unwrap(); + let error = client.execute(&request_spec, &options).err().unwrap(); if let HttpError::Libcurl { code, description, @@ -744,9 +755,9 @@ fn test_timeout() { timeout: Duration::from_millis(100), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("http://localhost:8000/timeout".to_string()); - let error = client.execute(&request_spec).err().unwrap(); + let error = client.execute(&request_spec, &options).err().unwrap(); assert!(matches!(error, HttpError::Libcurl { .. })); if let HttpError::Libcurl { code, @@ -766,7 +777,7 @@ fn test_accept_encoding() { compressed: true, ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = RequestSpec { method: Method::Get, @@ -779,7 +790,7 @@ fn test_accept_encoding() { body: Body::Binary(vec![]), content_type: None, }; - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Accept-Encoding".to_string(), value: "gzip, deflate, br".to_string(), @@ -797,13 +808,13 @@ fn test_connect_timeout() { connect_timeout: Duration::from_secs(1), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("http://10.0.0.0".to_string()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://10.0.0.0' --connect-timeout 1".to_string() ); - let error = client.execute(&request_spec).err().unwrap(); + let error = client.execute(&request_spec, &options).err().unwrap(); assert!(matches!(error, HttpError::Libcurl { .. })); if let HttpError::Libcurl { code, @@ -829,11 +840,12 @@ fn test_connect_timeout() { } // endregion -// region cookie +// region Cookie #[test] fn test_cookie() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Get, url: "http://localhost:8000/cookies/set-request-cookie1-valueA".to_string(), @@ -849,14 +861,14 @@ fn test_cookie() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/cookies/set-request-cookie1-valueA' --cookie 'cookie1=valueA'" .to_string() ); //assert_eq!(request.cookies(), vec!["cookie1=valueA".to_string(),]); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Cookie".to_string(), value: "cookie1=valueA".to_string(), @@ -875,13 +887,14 @@ fn test_cookie() { body: Body::Binary(vec![]), content_type: None, }; - let (_request, response) = client.execute(&request_spec).unwrap(); + let (_request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(response.status, 200); } #[test] fn test_multiple_request_cookies() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = RequestSpec { method: Method::Get, url: "http://localhost:8000/cookies/set-multiple-request-cookies".to_string(), @@ -907,11 +920,11 @@ fn test_multiple_request_cookies() { content_type: None, }; assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/cookies/set-multiple-request-cookies' --cookie 'user1=Bob; user2=Bill; user3=Bruce'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Cookie".to_string(), value: "user1=Bob; user2=Bill; user3=Bruce".to_string(), @@ -923,9 +936,10 @@ fn test_multiple_request_cookies() { #[test] fn test_cookie_storage() { let mut client = default_client(); + let options = ClientOptions::default(); let request_spec = default_get_request("http://localhost:8000/cookies/set-session-cookie2-valueA".to_string()); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!( request.url, "http://localhost:8000/cookies/set-session-cookie2-valueA".to_string() @@ -951,7 +965,7 @@ fn test_cookie_storage() { let request_spec = default_get_request( "http://localhost:8000/cookies/assert-that-cookie2-is-valueA".to_string(), ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert!(request.headers.contains(&Header { name: "Cookie".to_string(), value: "cookie2=valueA".to_string(), @@ -966,16 +980,16 @@ fn test_cookie_file() { cookie_input_file: Some("tests/cookies.txt".to_string()), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request( "http://localhost:8000/cookies/assert-that-cookie2-is-valueA".to_string(), ); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/cookies/assert-that-cookie2-is-valueA' --cookie tests/cookies.txt".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!( request.url, "http://localhost:8000/cookies/assert-that-cookie2-is-valueA" @@ -991,7 +1005,7 @@ fn test_cookie_file() { // endregion -// region proxy +// region Proxy #[test] fn test_proxy() { @@ -1000,13 +1014,13 @@ fn test_proxy() { proxy: Some("localhost:8888".to_string()), ..Default::default() }; - let mut client = Client::init(options); + let mut client = Client::init(&options); let request_spec = default_get_request("http://localhost:8000/proxy".to_string()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'http://localhost:8000/proxy' --proxy 'localhost:8888'".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.url, "http://localhost:8000/proxy"); assert_eq!(response.status, 200); } @@ -1019,15 +1033,15 @@ fn test_insecure() { insecure: true, ..Default::default() }; - let mut client = Client::init(options); - assert_eq!(client.options.curl_args(), vec!["--insecure".to_string()]); + let mut client = Client::init(&options); + assert_eq!(options.curl_args(), vec!["--insecure".to_string()]); let request_spec = default_get_request("https://localhost:8001/hello".to_string()); assert_eq!( - client.curl_command_line(&request_spec), + client.curl_command_line(&request_spec, &options), "curl 'https://localhost:8001/hello' --insecure".to_string() ); - let (request, response) = client.execute(&request_spec).unwrap(); + let (request, response) = client.execute(&request_spec, &options).unwrap(); assert_eq!(request.url, "https://localhost:8001/hello"); assert_eq!(response.status, 200); } diff --git a/packages/hurl/tests/runner.rs b/packages/hurl/tests/runner.rs index 6117d7f585a..bd421adca39 100644 --- a/packages/hurl/tests/runner.rs +++ b/packages/hurl/tests/runner.rs @@ -48,8 +48,8 @@ fn test_hurl_file() { let content = cli::read_to_string(filename).expect("Something went wrong reading the file"); let hurl_file = parser::parse_hurl_file(content.as_str()).unwrap(); let variables = HashMap::new(); - let options = http::ClientOptions::default(); - let mut client = http::Client::init(options); + let client_options = http::ClientOptions::default(); + let mut client = http::Client::init(&client_options); let mut lines: Vec<&str> = regex::Regex::new(r"\n|\r\n") .unwrap() .split(&content) @@ -57,7 +57,7 @@ fn test_hurl_file() { // edd an empty line at the end? lines.push(""); - let options = RunnerOptions { + let runner_options = RunnerOptions { fail_fast: false, variables, to_entry: None, @@ -74,15 +74,14 @@ fn test_hurl_file() { let _hurl_log = runner::run( hurl_file, - &mut client, - //&mut variables, filename, - &options, + &mut client, + &client_options, + &runner_options, &log_verbose, &log_error_message, &log_runner_error, ); - // assert_eq!(1,2) } #[cfg(test)] @@ -148,8 +147,8 @@ fn hello_request() -> Request { #[test] fn test_hello() { - let options = http::ClientOptions::default(); - let mut client = http::Client::init(options); + let client_options = http::ClientOptions::default(); + let mut client = http::Client::init(&client_options); let source_info = SourceInfo { start: Pos { line: 1, column: 1 }, end: Pos { line: 1, column: 1 }, @@ -188,7 +187,7 @@ fn test_hello() { line_terminators: vec![], }; let variables = HashMap::new(); - let options = RunnerOptions { + let runner_options = RunnerOptions { fail_fast: true, variables, to_entry: None, @@ -203,9 +202,10 @@ fn test_hello() { let log_runner_error: fn(&runner::Error, bool) = log_runner_error; let _hurl_log = runner::run( hurl_file, - &mut client, "filename", - &options, + &mut client, + &client_options, + &runner_options, &log_verbose, &log_error_message, &log_runner_error,