diff --git a/integration/tests/compressed.py b/integration/tests/compressed.py index 2403a55b5..1357c24e5 100644 --- a/integration/tests/compressed.py +++ b/integration/tests/compressed.py @@ -1,9 +1,10 @@ from tests import app -from flask import make_response +from flask import make_response, request from io import BytesIO @app.route("/compressed/gzip") def compressed_gzip(): + assert 'gzip' in request.headers['Accept-Encoding'] result = BytesIO() result.write(b'\x1f\x8b\x08\x00\xed\x0c\x84\x5f\x00\x03\xf3\x48\xcd\xc9\xc9\x57\x08\xcf\x2f\xca\x49\x51\x04\x00\xa3\x1c\x29\x1c\x0c\x00\x00\x00') data = result.getvalue() @@ -11,8 +12,10 @@ def compressed_gzip(): resp.headers['Content-Encoding'] = 'gzip' return resp + @app.route("/compressed/zlib") def compressed_zlib(): + assert 'deflate' in request.headers['Accept-Encoding'] result = BytesIO() result.write(b'\x78\x9c\xf3\x48\xcd\xc9\xc9\x57\x08\xcf\x2f\xca\x49\x51\x04\x00\x1c\x49\x04\x3e') data = result.getvalue() @@ -20,10 +23,11 @@ def compressed_zlib(): resp.headers['Content-Encoding'] = 'deflate' return resp + @app.route("/compressed/brotli") def compressed_brotli(): + assert 'br' in request.headers['Accept-Encoding'] result = BytesIO() - result.write(b'\x21\x2c\x00\x04\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x03') data = result.getvalue() resp = make_response(data) @@ -33,6 +37,7 @@ def compressed_brotli(): @app.route("/compressed/brotli_identity") def compressed_brotli_identity(): + assert 'br' in request.headers['Accept-Encoding'] result = BytesIO() result.write(b'\x21\x2c\x00\x04\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x03') diff --git a/src/bin/hurl.rs b/src/bin/hurl.rs index 7f1d4c520..afb171084 100644 --- a/src/bin/hurl.rs +++ b/src/bin/hurl.rs @@ -128,6 +128,12 @@ fn execute( let timeout = cli_options.timeout; let connect_timeout = cli_options.connect_timeout; let user = cli_options.user; + let compressed = cli_options.compressed; + let accept_encoding = if compressed { + Some("gzip, deflate, br".to_string()) + } else { + None + }; let options = http::ClientOptions { follow_location, max_redirect, @@ -139,6 +145,7 @@ fn execute( timeout, connect_timeout, user, + accept_encoding, }; let mut client = http::Client::init(options); diff --git a/src/http/client.rs b/src/http/client.rs index 37ae97b97..e592d2825 100644 --- a/src/http/client.rs +++ b/src/http/client.rs @@ -54,6 +54,7 @@ pub struct Client { pub max_redirect: Option, pub verbose: bool, pub authorization: Option, + pub accept_encoding: Option, } #[derive(Debug, Clone)] @@ -68,6 +69,7 @@ pub struct ClientOptions { pub timeout: Duration, pub connect_timeout: Duration, pub user: Option, + pub accept_encoding: Option, } impl Client { @@ -101,6 +103,7 @@ impl Client { h.connect_timeout(options.connect_timeout).unwrap(); let authorization = options.user.map(|user| base64::encode(user.as_bytes())); + let accept_encoding = options.accept_encoding; Client { handle: Box::new(h), follow_location: options.follow_location, @@ -108,6 +111,7 @@ impl Client { redirect_count: 0, verbose: options.verbose, authorization, + accept_encoding, } } @@ -316,6 +320,13 @@ impl Client { .unwrap(); } } + if let Some(accept_encoding) = self.accept_encoding.clone() { + if get_header_values(request.headers.clone(), "Accept-Encoding".to_string()).is_empty() + { + list.append(format!("Accept-Encoding: {}", accept_encoding).as_str()) + .unwrap(); + } + } self.handle.http_headers(list).unwrap(); } diff --git a/src/runner/hurl_file.rs b/src/runner/hurl_file.rs index 68ba05b06..79e070bd7 100644 --- a/src/runner/hurl_file.rs +++ b/src/runner/hurl_file.rs @@ -62,6 +62,7 @@ use super::value::Value; /// timeout: Default::default(), /// connect_timeout: Default::default(), /// user: None, +/// accept_encoding: None /// }; /// let mut client = http::Client::init(options); /// diff --git a/tests/libcurl.rs b/tests/libcurl.rs index c6b563cce..ad6574948 100644 --- a/tests/libcurl.rs +++ b/tests/libcurl.rs @@ -66,6 +66,7 @@ fn default_client() -> Client { timeout: Default::default(), connect_timeout: Duration::from_secs(300), user: None, + accept_encoding: None, }; Client::init(options) } @@ -98,11 +99,11 @@ fn test_hello() { assert_eq!(response.headers.len(), 4); assert!(response.headers.contains(&Header { name: "Content-Length".to_string(), - value: "12".to_string() + value: "12".to_string(), })); assert!(response.headers.contains(&Header { name: "Content-Type".to_string(), - value: "text/html; charset=utf-8".to_string() + value: "text/html; charset=utf-8".to_string(), })); assert_eq!(response.get_header_values("Date".to_string()).len(), 1); } @@ -308,6 +309,7 @@ fn test_follow_location() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let response = client.execute(&request, 0).unwrap(); @@ -342,6 +344,7 @@ fn test_max_redirect() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request("http://localhost:8000/redirect".to_string()); @@ -466,6 +469,7 @@ fn test_basic_authentication() { timeout: Default::default(), connect_timeout: Duration::from_secs(300), user: Some("bob:secret".to_string()), + accept_encoding: None, }; let mut client = Client::init(options); let request = Request { @@ -514,6 +518,7 @@ fn test_error_fail_to_connect() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request("http://localhost:8000/hello".to_string()); @@ -534,6 +539,7 @@ fn test_error_could_not_resolve_proxy_name() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request("http://localhost:8000/hello".to_string()); @@ -554,6 +560,7 @@ fn test_timeout() { timeout: Duration::from_millis(100), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request("http://localhost:8000/timeout".to_string()); @@ -561,6 +568,41 @@ fn test_timeout() { assert_eq!(error, HttpError::Timeout); } +#[test] +fn test_accept_encoding() { + let options = ClientOptions { + follow_location: false, + max_redirect: None, + cookie_input_file: None, + proxy: None, + no_proxy: None, + verbose: true, + insecure: false, + timeout: Default::default(), + connect_timeout: Duration::from_secs(300), + user: None, + accept_encoding: Some("gzip".to_string()), + }; + let mut client = Client::init(options); + let request = Request { + method: Method::Get, + url: "http://localhost:8000/compressed/gzip".to_string(), + headers: vec![], + querystring: vec![], + form: vec![], + multipart: vec![], + cookies: vec![], + body: vec![], + content_type: None, + }; + let response = client.execute(&request, 0).unwrap(); + assert_eq!(response.status, 200); + assert!(response.headers.contains(&Header { + name: "Content-Length".to_string(), + value: "32".to_string(), + })); +} + // // TODO: find a way to test it locally // #[test] @@ -576,13 +618,13 @@ fn test_connect_timeout() { timeout: Default::default(), connect_timeout: Duration::from_secs(1), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request("http://example.com:81".to_string()); let error = client.execute(&request, 0).err().unwrap(); assert_eq!(error, HttpError::Timeout); } - // endregion // region cookie @@ -701,6 +743,7 @@ fn test_cookie_file() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request( @@ -729,6 +772,7 @@ fn test_proxy() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = Client::init(options); let request = default_get_request("http://localhost:8000/hello".to_string()); diff --git a/tests/runner.rs b/tests/runner.rs index 4dcf540a4..34cd21be0 100644 --- a/tests/runner.rs +++ b/tests/runner.rs @@ -54,6 +54,7 @@ fn test_hurl_file() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = http::Client::init(options); let mut lines: Vec<&str> = regex::Regex::new(r"\n|\r\n") @@ -161,6 +162,7 @@ fn test_hello() { timeout: Default::default(), connect_timeout: Default::default(), user: None, + accept_encoding: None, }; let mut client = http::Client::init(options); let source_info = SourceInfo {