add option --compressed

This commit is contained in:
Fabrice Reix 2020-10-11 21:13:41 +02:00
parent 00de621f1c
commit 8a46b0b2e3
13 changed files with 324 additions and 138 deletions

View File

@ -130,6 +130,11 @@ Read cookies from file (using the Netscape cookie file format).
Combined with [-c, --cookie-jar](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
### --compressed
Request a compressed response using one of the algorithms br, gzip, deflate and automatically decompress the content.
### --connect-timeout <seconds> {#connect-timeout}
Maximum time in seconds that you allow hurl's connection to take.

View File

@ -1,2 +1,2 @@
<!DOCTYPE html>
<html><head><title>Hurl Report</title><link rel="stylesheet" type="text/css" href="report.css"></head><body><h2>Hurl Report</h2><div class="date">Sun, 11 Oct 2020 16:54:45 +0200</div><table><thead><tr><td>filename</td><td>duration</td></tr></thead><tbody><tr><td class="success">tests/assert_base64.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/assert_header.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/assert_json.hurl</td><td>0.011s</td></tr><tr><td class="success">tests/assert_match.hurl</td><td>0.021s</td></tr><tr><td class="success">tests/assert_regex.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/assert_xpath.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/bytes.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/capture_and_assert.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/captures.hurl</td><td>0.012s</td></tr><tr><td class="success">tests/cookies.hurl</td><td>0.018s</td></tr><tr><td class="success">tests/cookie_storage.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/delete.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/empty.hurl</td><td>0s</td></tr><tr><td class="success">tests/encoding.hurl</td><td>0.007s</td></tr><tr><td class="failure">tests/error_assert_base64.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_file.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_header_not_found.hurl</td><td>0.007s</td></tr><tr><td class="failure">tests/error_assert_header_value.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_http_version.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_assert_invalid_predicate_type.hurl</td><td>0.007s</td></tr><tr><td class="failure">tests/error_assert_match_utf8.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_assert_query_cookie.hurl</td><td>0.008s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_regex.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_xpath.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_status.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_template_variable_not_found.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_value_error.hurl</td><td>0.008s</td></tr><tr><td class="failure">tests/error_assert_variable.hurl</td><td>0.008s</td></tr><tr><td class="failure">tests/error_file_read_access.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_http_connection.hurl</td><td>0.06s</td></tr><tr><td class="failure">tests/error_invalid_jsonpath.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_invalid_url.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_invalid_xml.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_multipart_form_data.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_predicate.hurl</td><td>0.016s</td></tr><tr><td class="failure">tests/error_query_header_not_found.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_query_invalid_json.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_query_invalid_utf8.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_template_variable_not_found.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_template_variable_not_renderable.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/error_timeout.hurl</td><td>2.007s</td></tr><tr><td class="failure">tests/follow_redirect.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/form_params.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/headers.hurl</td><td>0.014s</td></tr><tr><td class="success">tests/hello.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/multipart_form_data.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/no_entry.hurl</td><td>0s</td></tr><tr><td class="success">tests/output.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/patch.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/post_base64.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/post_file.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/post_json.hurl</td><td>0.017s</td></tr><tr><td class="success">tests/post_multilines.hurl</td><td>0.009s</td></tr><tr><td class="success">tests/post_xml.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/predicates-string.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/put.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/querystring_params.hurl</td><td>0.011s</td></tr><tr><td class="success">tests/redirect.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/utf8.hurl</td><td>0.006s</td></tr></tbody></table></body></html>
<html><head><title>Hurl Report</title><link rel="stylesheet" type="text/css" href="report.css"></head><body><h2>Hurl Report</h2><div class="date">Mon, 12 Oct 2020 10:24:25 +0200</div><table><thead><tr><td>filename</td><td>duration</td></tr></thead><tbody><tr><td class="success">tests/assert_base64.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/assert_header.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/assert_json.hurl</td><td>0.015s</td></tr><tr><td class="success">tests/assert_match.hurl</td><td>0.033s</td></tr><tr><td class="success">tests/assert_regex.hurl</td><td>0.009s</td></tr><tr><td class="success">tests/assert_xpath.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/bytes.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/capture_and_assert.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/captures.hurl</td><td>0.014s</td></tr><tr><td class="failure">tests/compressed.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/cookies.hurl</td><td>0.021s</td></tr><tr><td class="success">tests/cookie_storage.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/delete.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/empty.hurl</td><td>0s</td></tr><tr><td class="success">tests/encoding.hurl</td><td>0.007s</td></tr><tr><td class="failure">tests/error_assert_base64.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_assert_file.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_header_not_found.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_header_value.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_http_version.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_assert_invalid_predicate_type.hurl</td><td>0.008s</td></tr><tr><td class="failure">tests/error_assert_match_utf8.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_query_cookie.hurl</td><td>0.01s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_regex.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_xpath.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_status.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_assert_template_variable_not_found.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_value_error.hurl</td><td>0.01s</td></tr><tr><td class="failure">tests/error_assert_variable.hurl</td><td>0.008s</td></tr><tr><td class="failure">tests/error_file_read_access.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_http_connection.hurl</td><td>0.124s</td></tr><tr><td class="failure">tests/error_invalid_jsonpath.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_invalid_url.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_invalid_xml.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_multipart_form_data.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_predicate.hurl</td><td>0.021s</td></tr><tr><td class="failure">tests/error_query_header_not_found.hurl</td><td>0.005s</td></tr><tr><td class="failure">tests/error_query_invalid_json.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_query_invalid_utf8.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_template_variable_not_found.hurl</td><td>0s</td></tr><tr><td class="failure">tests/error_template_variable_not_renderable.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/error_timeout.hurl</td><td>2.007s</td></tr><tr><td class="failure">tests/follow_redirect.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/form_params.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/headers.hurl</td><td>0.014s</td></tr><tr><td class="success">tests/hello.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/multipart_form_data.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/no_entry.hurl</td><td>0s</td></tr><tr><td class="success">tests/output.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/patch.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/post_base64.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/post_file.hurl</td><td>0.006s</td></tr><tr><td class="success">tests/post_json.hurl</td><td>0.019s</td></tr><tr><td class="success">tests/post_multilines.hurl</td><td>0.009s</td></tr><tr><td class="success">tests/post_xml.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/predicates-string.hurl</td><td>0.009s</td></tr><tr><td class="success">tests/put.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/querystring_params.hurl</td><td>0.014s</td></tr><tr><td class="success">tests/redirect.hurl</td><td>0.009s</td></tr><tr><td class="success">tests/utf8.hurl</td><td>0.006s</td></tr></tbody></table></body></html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,13 @@
GET http://localhost:8000/compressed/gzip
HTTP/1.0 200
Content-Length: 32
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
```Hello World!```
# -- COMPRESSED HAS NO EFFECT ON NON-COMPRESSED
GET http://localhost:8000/compressed/none
HTTP/1.0 200
Content-Length: 12
Content-Type: text/html; charset=utf-8
```Hello World!```

View File

@ -0,0 +1 @@
--compressed

View File

@ -0,0 +1 @@
Hello World!

View File

@ -0,0 +1,20 @@
from tests import app
from flask import make_response
from io import BytesIO
@app.route("/compressed/gzip")
def compressed_gzip():
result = BytesIO()
# echo -n 'Hello World!' | gzip -f | hexdump -C
#result.write(b'\x1f\x8b\x08\x00\x0e\x2e\x83\x5f\x00\x03\xf3\x48\xcd\xc9\xc9\x57\x08\xcf\x2f\xca\x49\x51\xe4\x02\x00\xdd\xdd\x14\x7d\x0d')
# 1f 8b 08 00 ed 0c 84 5f 00 03 f3 48 cd c9 c9 57 08 cf 2f ca 49 51 04 00 a3 1c 29 1c 0c 00 00 00
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()
resp = make_response(data)
resp.headers['Content-Encoding'] = 'gzip'
return resp
@app.route("/compressed/none")
def compressed_none():
return 'Hello World!'

View File

@ -50,6 +50,7 @@ pub struct CLIOptions {
pub cookie_input_file: Option<String>,
pub timeout: Duration,
pub connect_timeout: Duration,
pub compressed: bool,
}
fn execute(
@ -123,6 +124,7 @@ fn execute(
let timeout = cli_options.timeout;
let connect_timeout = cli_options.connect_timeout;
let compressed = cli_options.compressed;
let options = http::ClientOptions {
follow_location,
max_redirect,
@ -133,6 +135,7 @@ fn execute(
insecure,
timeout,
connect_timeout,
compressed,
};
let mut client = http::Client::init(options);
@ -307,6 +310,11 @@ fn app() -> clap::App<'static, 'static> {
.conflicts_with("no-color")
.help("Colorize Output"),
)
.arg(
clap::Arg::with_name("compressed")
.long("compressed")
.help("Request compressed response (using deflate or gzip)"),
)
.arg(
clap::Arg::with_name("connect_timeout")
.long("connect-timeout")
@ -498,6 +506,7 @@ fn parse_options(matches: ArgMatches) -> Result<CLIOptions, cli::CLIError> {
}
},
};
let compressed = matches.is_present("compressed");
Ok(CLIOptions {
verbose,
@ -513,6 +522,7 @@ fn parse_options(matches: ArgMatches) -> Result<CLIOptions, cli::CLIError> {
cookie_input_file,
timeout,
connect_timeout,
compressed,
})
}

View File

@ -65,6 +65,7 @@ pub struct ClientOptions {
pub insecure: bool,
pub timeout: Duration,
pub connect_timeout: Duration,
pub compressed: bool,
}
impl Client {
@ -97,6 +98,9 @@ impl Client {
h.timeout(options.timeout).unwrap();
h.connect_timeout(options.connect_timeout).unwrap();
if options.compressed {
h.accept_encoding("br, gzip, deflate").unwrap();
}
Client {
handle: Box::new(h),
follow_location: options.follow_location,

View File

@ -60,7 +60,8 @@ use super::value::Value;
/// verbose: false,
/// insecure: false,
/// timeout: Default::default(),
/// connect_timeout: Default::default()
/// connect_timeout: Default::default(),
/// compressed: false,
/// };
/// let mut client = http::Client::init(options);
///

View File

@ -65,6 +65,7 @@ fn default_client() -> Client {
insecure: false,
timeout: Default::default(),
connect_timeout: Duration::from_secs(300),
compressed: false,
};
Client::init(options)
}
@ -306,6 +307,7 @@ fn test_follow_location() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let response = client.execute(&request, 0).unwrap();
@ -339,6 +341,7 @@ fn test_max_redirect() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/redirect".to_string());
@ -427,6 +430,67 @@ fn test_post_bytes() {
// endregion
// region compressed
#[test]
fn test_compressed() {
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),
compressed: true,
};
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_eq!(response.body, b"Hello World!".to_vec());
assert!(response.headers.contains(&Header {
name: "Content-Length".to_string(),
value: "32".to_string()
}));
assert!(response.headers.contains(&Header {
name: "Content-Encoding".to_string(),
value: "gzip".to_string()
}));
let request = Request {
method: Method::Get,
url: "http://localhost:8000/compressed/none".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_eq!(response.body, b"Hello World!".to_vec());
assert!(response.headers.contains(&Header {
name: "Content-Length".to_string(),
value: "12".to_string()
}));
}
// endregion
// region error
#[test]
@ -455,6 +519,7 @@ fn test_error_fail_to_connect() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/hello".to_string());
@ -474,6 +539,7 @@ fn test_error_could_not_resolve_proxy_name() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/hello".to_string());
@ -493,6 +559,7 @@ fn test_timeout() {
insecure: false,
timeout: Duration::from_millis(100),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/timeout".to_string());
@ -514,6 +581,7 @@ fn test_connect_timeout() {
insecure: false,
timeout: Default::default(),
connect_timeout: Duration::from_secs(1),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request("http://example.com:81".to_string());
@ -616,6 +684,7 @@ fn test_cookie_file() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request(
@ -643,6 +712,7 @@ fn test_proxy() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/hello".to_string());

View File

@ -53,6 +53,7 @@ fn test_hurl_file() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = http::Client::init(options);
let mut lines: Vec<&str> = regex::Regex::new(r"\n|\r\n")
@ -159,6 +160,7 @@ fn test_hello() {
insecure: false,
timeout: Default::default(),
connect_timeout: Default::default(),
compressed: false,
};
let mut client = http::Client::init(options);
let source_info = SourceInfo {