Add Accept-Encoding header with --compressed option

This commit is contained in:
Fabrice Reix 2020-10-27 08:35:14 +01:00
parent 78921ecdf7
commit e90eb37b27
6 changed files with 75 additions and 5 deletions

View File

@ -1,9 +1,10 @@
from tests import app from tests import app
from flask import make_response from flask import make_response, request
from io import BytesIO from io import BytesIO
@app.route("/compressed/gzip") @app.route("/compressed/gzip")
def compressed_gzip(): def compressed_gzip():
assert 'gzip' in request.headers['Accept-Encoding']
result = BytesIO() 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') 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() data = result.getvalue()
@ -11,8 +12,10 @@ def compressed_gzip():
resp.headers['Content-Encoding'] = 'gzip' resp.headers['Content-Encoding'] = 'gzip'
return resp return resp
@app.route("/compressed/zlib") @app.route("/compressed/zlib")
def compressed_zlib(): def compressed_zlib():
assert 'deflate' in request.headers['Accept-Encoding']
result = BytesIO() 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') 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() data = result.getvalue()
@ -20,10 +23,11 @@ def compressed_zlib():
resp.headers['Content-Encoding'] = 'deflate' resp.headers['Content-Encoding'] = 'deflate'
return resp return resp
@app.route("/compressed/brotli") @app.route("/compressed/brotli")
def compressed_brotli(): def compressed_brotli():
assert 'br' in request.headers['Accept-Encoding']
result = BytesIO() result = BytesIO()
result.write(b'\x21\x2c\x00\x04\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x03') result.write(b'\x21\x2c\x00\x04\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x03')
data = result.getvalue() data = result.getvalue()
resp = make_response(data) resp = make_response(data)
@ -33,6 +37,7 @@ def compressed_brotli():
@app.route("/compressed/brotli_identity") @app.route("/compressed/brotli_identity")
def compressed_brotli_identity(): def compressed_brotli_identity():
assert 'br' in request.headers['Accept-Encoding']
result = BytesIO() result = BytesIO()
result.write(b'\x21\x2c\x00\x04\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x03') result.write(b'\x21\x2c\x00\x04\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x03')

View File

@ -128,6 +128,12 @@ fn execute(
let timeout = cli_options.timeout; let timeout = cli_options.timeout;
let connect_timeout = cli_options.connect_timeout; let connect_timeout = cli_options.connect_timeout;
let user = cli_options.user; 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 { let options = http::ClientOptions {
follow_location, follow_location,
max_redirect, max_redirect,
@ -139,6 +145,7 @@ fn execute(
timeout, timeout,
connect_timeout, connect_timeout,
user, user,
accept_encoding,
}; };
let mut client = http::Client::init(options); let mut client = http::Client::init(options);

View File

@ -54,6 +54,7 @@ pub struct Client {
pub max_redirect: Option<usize>, pub max_redirect: Option<usize>,
pub verbose: bool, pub verbose: bool,
pub authorization: Option<String>, pub authorization: Option<String>,
pub accept_encoding: Option<String>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -68,6 +69,7 @@ pub struct ClientOptions {
pub timeout: Duration, pub timeout: Duration,
pub connect_timeout: Duration, pub connect_timeout: Duration,
pub user: Option<String>, pub user: Option<String>,
pub accept_encoding: Option<String>,
} }
impl Client { impl Client {
@ -101,6 +103,7 @@ impl Client {
h.connect_timeout(options.connect_timeout).unwrap(); h.connect_timeout(options.connect_timeout).unwrap();
let authorization = options.user.map(|user| base64::encode(user.as_bytes())); let authorization = options.user.map(|user| base64::encode(user.as_bytes()));
let accept_encoding = options.accept_encoding;
Client { Client {
handle: Box::new(h), handle: Box::new(h),
follow_location: options.follow_location, follow_location: options.follow_location,
@ -108,6 +111,7 @@ impl Client {
redirect_count: 0, redirect_count: 0,
verbose: options.verbose, verbose: options.verbose,
authorization, authorization,
accept_encoding,
} }
} }
@ -316,6 +320,13 @@ impl Client {
.unwrap(); .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(); self.handle.http_headers(list).unwrap();
} }

View File

@ -62,6 +62,7 @@ use super::value::Value;
/// timeout: Default::default(), /// timeout: Default::default(),
/// connect_timeout: Default::default(), /// connect_timeout: Default::default(),
/// user: None, /// user: None,
/// accept_encoding: None
/// }; /// };
/// let mut client = http::Client::init(options); /// let mut client = http::Client::init(options);
/// ///

View File

@ -66,6 +66,7 @@ fn default_client() -> Client {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Duration::from_secs(300), connect_timeout: Duration::from_secs(300),
user: None, user: None,
accept_encoding: None,
}; };
Client::init(options) Client::init(options)
} }
@ -98,11 +99,11 @@ fn test_hello() {
assert_eq!(response.headers.len(), 4); assert_eq!(response.headers.len(), 4);
assert!(response.headers.contains(&Header { assert!(response.headers.contains(&Header {
name: "Content-Length".to_string(), name: "Content-Length".to_string(),
value: "12".to_string() value: "12".to_string(),
})); }));
assert!(response.headers.contains(&Header { assert!(response.headers.contains(&Header {
name: "Content-Type".to_string(), 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); assert_eq!(response.get_header_values("Date".to_string()).len(), 1);
} }
@ -308,6 +309,7 @@ fn test_follow_location() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let response = client.execute(&request, 0).unwrap(); let response = client.execute(&request, 0).unwrap();
@ -342,6 +344,7 @@ fn test_max_redirect() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/redirect".to_string()); let request = default_get_request("http://localhost:8000/redirect".to_string());
@ -466,6 +469,7 @@ fn test_basic_authentication() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Duration::from_secs(300), connect_timeout: Duration::from_secs(300),
user: Some("bob:secret".to_string()), user: Some("bob:secret".to_string()),
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = Request { let request = Request {
@ -514,6 +518,7 @@ fn test_error_fail_to_connect() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/hello".to_string()); 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(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/hello".to_string()); let request = default_get_request("http://localhost:8000/hello".to_string());
@ -554,6 +560,7 @@ fn test_timeout() {
timeout: Duration::from_millis(100), timeout: Duration::from_millis(100),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/timeout".to_string()); let request = default_get_request("http://localhost:8000/timeout".to_string());
@ -561,6 +568,41 @@ fn test_timeout() {
assert_eq!(error, HttpError::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 // TODO: find a way to test it locally
// #[test] // #[test]
@ -576,13 +618,13 @@ fn test_connect_timeout() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Duration::from_secs(1), connect_timeout: Duration::from_secs(1),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request("http://example.com:81".to_string()); let request = default_get_request("http://example.com:81".to_string());
let error = client.execute(&request, 0).err().unwrap(); let error = client.execute(&request, 0).err().unwrap();
assert_eq!(error, HttpError::Timeout); assert_eq!(error, HttpError::Timeout);
} }
// endregion // endregion
// region cookie // region cookie
@ -701,6 +743,7 @@ fn test_cookie_file() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request( let request = default_get_request(
@ -729,6 +772,7 @@ fn test_proxy() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = Client::init(options); let mut client = Client::init(options);
let request = default_get_request("http://localhost:8000/hello".to_string()); let request = default_get_request("http://localhost:8000/hello".to_string());

View File

@ -54,6 +54,7 @@ fn test_hurl_file() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = http::Client::init(options); let mut client = http::Client::init(options);
let mut lines: Vec<&str> = regex::Regex::new(r"\n|\r\n") let mut lines: Vec<&str> = regex::Regex::new(r"\n|\r\n")
@ -161,6 +162,7 @@ fn test_hello() {
timeout: Default::default(), timeout: Default::default(),
connect_timeout: Default::default(), connect_timeout: Default::default(),
user: None, user: None,
accept_encoding: None,
}; };
let mut client = http::Client::init(options); let mut client = http::Client::init(options);
let source_info = SourceInfo { let source_info = SourceInfo {