mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2025-01-04 17:41:45 +03:00
Merge pull request #30 from Orange-OpenSource/feature/add-timeout-option
Add timeout option (--connect-timeout and --max-time)
This commit is contained in:
commit
0fcd63834a
12
docs/hurl.1
12
docs/hurl.1
@ -133,6 +133,12 @@ Read cookies from file (using the Netscape cookie file format).
|
|||||||
Combined with \fI-c, --cookie-jar\fP, you can simulate a cookie storage between successive Hurl runs.
|
Combined with \fI-c, --cookie-jar\fP, you can simulate a cookie storage between successive Hurl runs.
|
||||||
|
|
||||||
|
|
||||||
|
.IP "--connect-timeout <seconds> "
|
||||||
|
|
||||||
|
Maximum time in seconds that you allow hurl's connection to take.
|
||||||
|
|
||||||
|
See also \fI-m, --max-time\fP option.
|
||||||
|
|
||||||
|
|
||||||
.IP "-c, --cookie-jar <filename> "
|
.IP "-c, --cookie-jar <filename> "
|
||||||
|
|
||||||
@ -202,6 +208,12 @@ This option explicitly allows Hurl to perform "insecure" SSL connections and tra
|
|||||||
Follow redirect. You can limit the amount of redirects to follow by using the \fI--max-redirs\fP option.
|
Follow redirect. You can limit the amount of redirects to follow by using the \fI--max-redirs\fP option.
|
||||||
|
|
||||||
|
|
||||||
|
.IP "-m, --max-time <seconds> "
|
||||||
|
|
||||||
|
Maximum time in seconds that you allow a request/response to take. This is the standard timeout.
|
||||||
|
|
||||||
|
See also \fI--connect-timeout\fP option.
|
||||||
|
|
||||||
|
|
||||||
.IP "--max-redirs <num> "
|
.IP "--max-redirs <num> "
|
||||||
|
|
||||||
|
12
docs/hurl.md
12
docs/hurl.md
@ -130,6 +130,12 @@ 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.
|
Combined with [-c, --cookie-jar](#cookie-jar), you can simulate a cookie storage between successive Hurl runs.
|
||||||
|
|
||||||
|
|
||||||
|
### --connect-timeout <seconds> {#connect-timeout}
|
||||||
|
|
||||||
|
Maximum time in seconds that you allow hurl's connection to take.
|
||||||
|
|
||||||
|
See also [-m, --max-time](#max-time) option.
|
||||||
|
|
||||||
|
|
||||||
### -c, --cookie-jar <filename> {#cookie-jar}
|
### -c, --cookie-jar <filename> {#cookie-jar}
|
||||||
|
|
||||||
@ -199,6 +205,12 @@ This option explicitly allows Hurl to perform "insecure" SSL connections and tra
|
|||||||
Follow redirect. You can limit the amount of redirects to follow by using the [--max-redirs](#max-redirs) option.
|
Follow redirect. You can limit the amount of redirects to follow by using the [--max-redirs](#max-redirs) option.
|
||||||
|
|
||||||
|
|
||||||
|
### -m, --max-time <seconds> {#ax-time}
|
||||||
|
|
||||||
|
Maximum time in seconds that you allow a request/response to take. This is the standard timeout.
|
||||||
|
|
||||||
|
See also [--connect-timeout](#connect-timeout) option.
|
||||||
|
|
||||||
|
|
||||||
### --max-redirs <num> {#max-redirs}
|
### --max-redirs <num> {#max-redirs}
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
<!DOCTYPE html>
|
<!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">Wed, 23 Sep 2020 20:34: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.002s</td></tr><tr><td class="success">tests/assert_header.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/assert_json.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/assert_match.hurl</td><td>0.016s</td></tr><tr><td class="success">tests/assert_regex.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/assert_xpath.hurl</td><td>0.003s</td></tr><tr><td class="success">tests/bytes.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/capture_and_assert.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/captures.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/cookies.hurl</td><td>0.016s</td></tr><tr><td class="success">tests/cookie_storage.hurl</td><td>0.003s</td></tr><tr><td class="success">tests/delete.hurl</td><td>0.001s</td></tr><tr><td class="success">tests/empty.hurl</td><td>0s</td></tr><tr><td class="success">tests/encoding.hurl</td><td>0.003s</td></tr><tr><td class="failure">tests/error_assert_base64.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_file.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_header_not_found.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_header_value.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_http_version.hurl</td><td>0.001s</td></tr><tr><td class="failure">tests/error_assert_invalid_predicate_type.hurl</td><td>0.003s</td></tr><tr><td class="failure">tests/error_assert_match_utf8.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_query_cookie.hurl</td><td>0.004s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_regex.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_xpath.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_status.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_template_variable_not_found.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_value_error.hurl</td><td>0.004s</td></tr><tr><td class="failure">tests/error_assert_variable.hurl</td><td>0.005s</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.01s</td></tr><tr><td class="failure">tests/error_invalid_jsonpath.hurl</td><td>0.002s</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.002s</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.012s</td></tr><tr><td class="failure">tests/error_query_header_not_found.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_query_invalid_json.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_query_invalid_utf8.hurl</td><td>0.002s</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.002s</td></tr><tr><td class="failure">tests/follow_redirect.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/form_params.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/headers.hurl</td><td>0.011s</td></tr><tr><td class="success">tests/hello.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/multipart_form_data.hurl</td><td>0.003s</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.003s</td></tr><tr><td class="success">tests/patch.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/post_base64.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/post_file.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/post_json.hurl</td><td>0.015s</td></tr><tr><td class="success">tests/post_multilines.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/post_xml.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/predicates-string.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/put.hurl</td><td>0.001s</td></tr><tr><td class="success">tests/querystring_params.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/redirect.hurl</td><td>0.003s</td></tr><tr><td class="success">tests/utf8.hurl</td><td>0.002s</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">Thu, 24 Sep 2020 21:02:09 +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.002s</td></tr><tr><td class="success">tests/assert_header.hurl</td><td>0.003s</td></tr><tr><td class="success">tests/assert_json.hurl</td><td>0.009s</td></tr><tr><td class="success">tests/assert_match.hurl</td><td>0.016s</td></tr><tr><td class="success">tests/assert_regex.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/assert_xpath.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/bytes.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/capture_and_assert.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/captures.hurl</td><td>0.008s</td></tr><tr><td class="success">tests/cookies.hurl</td><td>0.016s</td></tr><tr><td class="success">tests/cookie_storage.hurl</td><td>0.003s</td></tr><tr><td class="success">tests/delete.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/empty.hurl</td><td>0s</td></tr><tr><td class="success">tests/encoding.hurl</td><td>0.006s</td></tr><tr><td class="failure">tests/error_assert_base64.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_file.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_header_not_found.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_header_value.hurl</td><td>0.001s</td></tr><tr><td class="failure">tests/error_assert_http_version.hurl</td><td>0.001s</td></tr><tr><td class="failure">tests/error_assert_invalid_predicate_type.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_match_utf8.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_query_cookie.hurl</td><td>0.004s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_regex.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_query_invalid_xpath.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_status.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_template_variable_not_found.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_assert_value_error.hurl</td><td>0.004s</td></tr><tr><td class="failure">tests/error_assert_variable.hurl</td><td>0.005s</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.006s</td></tr><tr><td class="failure">tests/error_invalid_jsonpath.hurl</td><td>0.002s</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.002s</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.013s</td></tr><tr><td class="failure">tests/error_query_header_not_found.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_query_invalid_json.hurl</td><td>0.002s</td></tr><tr><td class="failure">tests/error_query_invalid_utf8.hurl</td><td>0.002s</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.002s</td></tr><tr><td class="success">tests/error_timeout.hurl</td><td>2.004s</td></tr><tr><td class="failure">tests/follow_redirect.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/form_params.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/headers.hurl</td><td>0.011s</td></tr><tr><td class="success">tests/hello.hurl</td><td>0.003s</td></tr><tr><td class="success">tests/multipart_form_data.hurl</td><td>0.003s</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.003s</td></tr><tr><td class="success">tests/patch.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/post_base64.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/post_file.hurl</td><td>0.002s</td></tr><tr><td class="success">tests/post_json.hurl</td><td>0.015s</td></tr><tr><td class="success">tests/post_multilines.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/post_xml.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/predicates-string.hurl</td><td>0.005s</td></tr><tr><td class="success">tests/put.hurl</td><td>0.001s</td></tr><tr><td class="success">tests/querystring_params.hurl</td><td>0.007s</td></tr><tr><td class="success">tests/redirect.hurl</td><td>0.004s</td></tr><tr><td class="success">tests/utf8.hurl</td><td>0.002s</td></tr></tbody></table></body></html>
|
File diff suppressed because it is too large
Load Diff
7
integration/tests/error_timeout.err
Normal file
7
integration/tests/error_timeout.err
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
error: Http Connection
|
||||||
|
--> tests/error_timeout.hurl:1:5
|
||||||
|
|
|
||||||
|
1 | GET http://localhost:8000/timeout
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Timeout has been reached
|
||||||
|
|
|
||||||
|
|
1
integration/tests/error_timeout.exit
Normal file
1
integration/tests/error_timeout.exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
3
|
3
integration/tests/error_timeout.hurl
Normal file
3
integration/tests/error_timeout.hurl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
GET http://localhost:8000/timeout
|
||||||
|
|
||||||
|
|
1
integration/tests/error_timeout.options
Normal file
1
integration/tests/error_timeout.options
Normal file
@ -0,0 +1 @@
|
|||||||
|
--max-time 1
|
9
integration/tests/error_timeout.py
Normal file
9
integration/tests/error_timeout.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from tests import app
|
||||||
|
import time
|
||||||
|
|
||||||
|
@app.route('/timeout')
|
||||||
|
def timeout():
|
||||||
|
time.sleep(2)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
@ -36,6 +36,7 @@ use hurl::parser;
|
|||||||
use hurl::runner;
|
use hurl::runner;
|
||||||
use hurl::runner::core::*;
|
use hurl::runner::core::*;
|
||||||
use hurl::runner::log_deserialize;
|
use hurl::runner::log_deserialize;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct CLIOptions {
|
pub struct CLIOptions {
|
||||||
@ -50,6 +51,8 @@ pub struct CLIOptions {
|
|||||||
pub proxy: Option<String>,
|
pub proxy: Option<String>,
|
||||||
pub no_proxy: Option<String>,
|
pub no_proxy: Option<String>,
|
||||||
pub cookie_input_file: Option<String>,
|
pub cookie_input_file: Option<String>,
|
||||||
|
pub timeout: Duration,
|
||||||
|
pub connect_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(
|
fn execute(
|
||||||
@ -114,6 +117,9 @@ fn execute(
|
|||||||
let proxy = cli_options.proxy;
|
let proxy = cli_options.proxy;
|
||||||
let no_proxy = cli_options.no_proxy;
|
let no_proxy = cli_options.no_proxy;
|
||||||
let cookie_input_file = cli_options.cookie_input_file;
|
let cookie_input_file = cli_options.cookie_input_file;
|
||||||
|
|
||||||
|
let timeout = cli_options.timeout;
|
||||||
|
let connect_timeout = cli_options.connect_timeout;
|
||||||
let options = http::ClientOptions {
|
let options = http::ClientOptions {
|
||||||
follow_location,
|
follow_location,
|
||||||
max_redirect,
|
max_redirect,
|
||||||
@ -122,6 +128,8 @@ fn execute(
|
|||||||
no_proxy,
|
no_proxy,
|
||||||
verbose,
|
verbose,
|
||||||
insecure,
|
insecure,
|
||||||
|
timeout,
|
||||||
|
connect_timeout,
|
||||||
};
|
};
|
||||||
let mut client = http::Client::init(options);
|
let mut client = http::Client::init(options);
|
||||||
|
|
||||||
@ -298,6 +306,12 @@ fn app() -> clap::App<'static, 'static> {
|
|||||||
.conflicts_with("no-color")
|
.conflicts_with("no-color")
|
||||||
.help("Colorize Output"),
|
.help("Colorize Output"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::with_name("connect_timeout")
|
||||||
|
.long("connect-timeout")
|
||||||
|
.value_name("SECONDS")
|
||||||
|
.help("Maximum time allowed for connection"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::with_name("cookies_input_file")
|
clap::Arg::with_name("cookies_input_file")
|
||||||
.short("b")
|
.short("b")
|
||||||
@ -357,6 +371,14 @@ fn app() -> clap::App<'static, 'static> {
|
|||||||
.long("location")
|
.long("location")
|
||||||
.help("Follow redirects"),
|
.help("Follow redirects"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::with_name("max_time")
|
||||||
|
.long("max-time")
|
||||||
|
.short("m")
|
||||||
|
.value_name("NUM")
|
||||||
|
.allow_hyphen_values(true)
|
||||||
|
.help("Maximum time allowed for the transfer"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::with_name("max_redirects")
|
clap::Arg::with_name("max_redirects")
|
||||||
.long("max-redirs")
|
.long("max-redirs")
|
||||||
@ -447,7 +469,31 @@ fn parse_options(
|
|||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(cli::Error {
|
return Err(cli::Error {
|
||||||
message: "max_redirs option can not be parsed".to_string(),
|
message: "max_redirs option can not be parsed".to_string(),
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let timeout = match matches.value_of("max_time") {
|
||||||
|
None => Duration::from_secs(0),
|
||||||
|
Some(s) => match s.parse::<u64>() {
|
||||||
|
Ok(n) => Duration::from_secs(n),
|
||||||
|
Err(_) => {
|
||||||
|
return Err(cli::Error {
|
||||||
|
message: "max_time option can not be parsed".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let connect_timeout = match matches.value_of("connect_timeout") {
|
||||||
|
None => Duration::from_secs(300),
|
||||||
|
Some(s) => match s.parse::<u64>() {
|
||||||
|
Ok(n) => Duration::from_secs(n),
|
||||||
|
Err(_) => {
|
||||||
|
return Err(cli::Error {
|
||||||
|
message: "connect-timeout option can not be parsed".to_string(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -464,6 +510,8 @@ fn parse_options(
|
|||||||
proxy,
|
proxy,
|
||||||
no_proxy,
|
no_proxy,
|
||||||
cookie_input_file,
|
cookie_input_file,
|
||||||
|
timeout,
|
||||||
|
connect_timeout,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use std::str;
|
|||||||
use curl::easy;
|
use curl::easy;
|
||||||
use encoding::all::ISO_8859_1;
|
use encoding::all::ISO_8859_1;
|
||||||
use encoding::{DecoderTrap, Encoding};
|
use encoding::{DecoderTrap, Encoding};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use super::core::*;
|
use super::core::*;
|
||||||
use super::request::*;
|
use super::request::*;
|
||||||
@ -36,6 +37,7 @@ pub enum HttpError {
|
|||||||
CouldNotParseResponse,
|
CouldNotParseResponse,
|
||||||
SSLCertificate,
|
SSLCertificate,
|
||||||
InvalidUrl,
|
InvalidUrl,
|
||||||
|
Timeout,
|
||||||
Other { description: String, code: u32 },
|
Other { description: String, code: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +63,8 @@ pub struct ClientOptions {
|
|||||||
pub no_proxy: Option<String>,
|
pub no_proxy: Option<String>,
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
pub insecure: bool,
|
pub insecure: bool,
|
||||||
|
pub timeout: Duration,
|
||||||
|
pub connect_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -90,6 +94,9 @@ impl Client {
|
|||||||
h.ssl_verify_host(options.insecure).unwrap();
|
h.ssl_verify_host(options.insecure).unwrap();
|
||||||
h.ssl_verify_peer(options.insecure).unwrap();
|
h.ssl_verify_peer(options.insecure).unwrap();
|
||||||
|
|
||||||
|
h.timeout(options.timeout).unwrap();
|
||||||
|
h.connect_timeout(options.connect_timeout).unwrap();
|
||||||
|
|
||||||
Client {
|
Client {
|
||||||
handle: Box::new(h),
|
handle: Box::new(h),
|
||||||
follow_location: options.follow_location,
|
follow_location: options.follow_location,
|
||||||
@ -177,6 +184,7 @@ impl Client {
|
|||||||
5 => Err(HttpError::CouldNotResolveProxyName),
|
5 => Err(HttpError::CouldNotResolveProxyName),
|
||||||
6 => Err(HttpError::CouldNotResolveHost),
|
6 => Err(HttpError::CouldNotResolveHost),
|
||||||
7 => Err(HttpError::FailToConnect),
|
7 => Err(HttpError::FailToConnect),
|
||||||
|
28 => Err(HttpError::Timeout),
|
||||||
60 => Err(HttpError::SSLCertificate),
|
60 => Err(HttpError::SSLCertificate),
|
||||||
_ => Err(HttpError::Other {
|
_ => Err(HttpError::Other {
|
||||||
code: e.code(),
|
code: e.code(),
|
||||||
|
@ -122,6 +122,7 @@ pub enum RunnerError {
|
|||||||
CouldNotResolveProxyName,
|
CouldNotResolveProxyName,
|
||||||
CouldNotResolveHost,
|
CouldNotResolveHost,
|
||||||
FailToConnect,
|
FailToConnect,
|
||||||
|
Timeout,
|
||||||
TooManyRedirect,
|
TooManyRedirect,
|
||||||
CouldNotParseResponse,
|
CouldNotParseResponse,
|
||||||
SSLCertificate,
|
SSLCertificate,
|
||||||
@ -192,6 +193,7 @@ impl FormatError for Error {
|
|||||||
RunnerError::CouldNotResolveProxyName => "Http Connection".to_string(),
|
RunnerError::CouldNotResolveProxyName => "Http Connection".to_string(),
|
||||||
RunnerError::CouldNotResolveHost => "Http Connection".to_string(),
|
RunnerError::CouldNotResolveHost => "Http Connection".to_string(),
|
||||||
RunnerError::FailToConnect => "Http Connection".to_string(),
|
RunnerError::FailToConnect => "Http Connection".to_string(),
|
||||||
|
RunnerError::Timeout => "Http Connection".to_string(),
|
||||||
RunnerError::TooManyRedirect => "Http Connection".to_string(),
|
RunnerError::TooManyRedirect => "Http Connection".to_string(),
|
||||||
RunnerError::CouldNotParseResponse => "Http Connection".to_string(),
|
RunnerError::CouldNotParseResponse => "Http Connection".to_string(),
|
||||||
RunnerError::SSLCertificate => "Http Connection".to_string(),
|
RunnerError::SSLCertificate => "Http Connection".to_string(),
|
||||||
@ -230,6 +232,7 @@ impl FormatError for Error {
|
|||||||
RunnerError::CouldNotResolveProxyName => "Could not resolve proxy name".to_string(),
|
RunnerError::CouldNotResolveProxyName => "Could not resolve proxy name".to_string(),
|
||||||
RunnerError::CouldNotResolveHost => "Could not resolve host".to_string(),
|
RunnerError::CouldNotResolveHost => "Could not resolve host".to_string(),
|
||||||
RunnerError::FailToConnect => "Fail to connect".to_string(),
|
RunnerError::FailToConnect => "Fail to connect".to_string(),
|
||||||
|
RunnerError::Timeout => "Timeout has been reached".to_string(),
|
||||||
RunnerError::TooManyRedirect => "Too many redirect".to_string(),
|
RunnerError::TooManyRedirect => "Too many redirect".to_string(),
|
||||||
RunnerError::CouldNotParseResponse => "Could not parse response".to_string(),
|
RunnerError::CouldNotParseResponse => "Could not parse response".to_string(),
|
||||||
RunnerError::SSLCertificate => "SSl Certificate".to_string(),
|
RunnerError::SSLCertificate => "SSl Certificate".to_string(),
|
||||||
|
@ -105,6 +105,7 @@ pub fn run(
|
|||||||
HttpError::CouldNotResolveProxyName => RunnerError::CouldNotResolveProxyName,
|
HttpError::CouldNotResolveProxyName => RunnerError::CouldNotResolveProxyName,
|
||||||
HttpError::CouldNotResolveHost => RunnerError::CouldNotResolveHost,
|
HttpError::CouldNotResolveHost => RunnerError::CouldNotResolveHost,
|
||||||
HttpError::FailToConnect => RunnerError::FailToConnect,
|
HttpError::FailToConnect => RunnerError::FailToConnect,
|
||||||
|
HttpError::Timeout => RunnerError::Timeout,
|
||||||
HttpError::TooManyRedirect => RunnerError::TooManyRedirect,
|
HttpError::TooManyRedirect => RunnerError::TooManyRedirect,
|
||||||
HttpError::CouldNotParseResponse => RunnerError::CouldNotParseResponse,
|
HttpError::CouldNotParseResponse => RunnerError::CouldNotParseResponse,
|
||||||
HttpError::SSLCertificate => RunnerError::SSLCertificate,
|
HttpError::SSLCertificate => RunnerError::SSLCertificate,
|
||||||
|
@ -53,6 +53,8 @@ use crate::core::common::FormatError;
|
|||||||
/// no_proxy: None,
|
/// no_proxy: None,
|
||||||
/// verbose: false,
|
/// verbose: false,
|
||||||
/// insecure: false,
|
/// insecure: false,
|
||||||
|
/// timeout: Default::default(),
|
||||||
|
/// connect_timeout: Default::default()
|
||||||
/// };
|
/// };
|
||||||
/// let mut client = http::Client::init(options);
|
/// let mut client = http::Client::init(options);
|
||||||
///
|
///
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
use curl::easy::Easy;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
use std::time::Duration;
|
||||||
use curl::easy::Easy;
|
|
||||||
|
|
||||||
use hurl::http::*;
|
use hurl::http::*;
|
||||||
|
|
||||||
@ -63,6 +63,8 @@ fn default_client() -> Client {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: true,
|
verbose: true,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Duration::from_secs(300),
|
||||||
};
|
};
|
||||||
Client::init(options)
|
Client::init(options)
|
||||||
}
|
}
|
||||||
@ -302,6 +304,8 @@ fn test_follow_location() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Default::default(),
|
||||||
};
|
};
|
||||||
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();
|
||||||
@ -333,6 +337,8 @@ fn test_max_redirect() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Default::default(),
|
||||||
};
|
};
|
||||||
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());
|
||||||
@ -447,6 +453,8 @@ fn test_error_fail_to_connect() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: true,
|
verbose: true,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: 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 request = default_get_request("http://localhost:8000/hello".to_string());
|
||||||
@ -464,6 +472,8 @@ fn test_error_could_not_resolve_proxy_name() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: 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 request = default_get_request("http://localhost:8000/hello".to_string());
|
||||||
@ -471,6 +481,46 @@ fn test_error_could_not_resolve_proxy_name() {
|
|||||||
assert_eq!(error, HttpError::CouldNotResolveProxyName);
|
assert_eq!(error, HttpError::CouldNotResolveProxyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeout() {
|
||||||
|
let options = ClientOptions {
|
||||||
|
follow_location: false,
|
||||||
|
max_redirect: None,
|
||||||
|
cookie_input_file: None,
|
||||||
|
proxy: None,
|
||||||
|
no_proxy: None,
|
||||||
|
verbose: false,
|
||||||
|
insecure: false,
|
||||||
|
timeout: Duration::from_millis(100),
|
||||||
|
connect_timeout: Default::default(),
|
||||||
|
};
|
||||||
|
let mut client = Client::init(options);
|
||||||
|
let request = default_get_request("http://localhost:8000/timeout".to_string());
|
||||||
|
let error = client.execute(&request, 0).err().unwrap();
|
||||||
|
assert_eq!(error, HttpError::Timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: find a way to test it locally
|
||||||
|
// #[test]
|
||||||
|
fn test_connect_timeout() {
|
||||||
|
let options = ClientOptions {
|
||||||
|
follow_location: false,
|
||||||
|
max_redirect: None,
|
||||||
|
cookie_input_file: None,
|
||||||
|
proxy: None,
|
||||||
|
no_proxy: None,
|
||||||
|
verbose: false,
|
||||||
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Duration::from_secs(1),
|
||||||
|
};
|
||||||
|
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
|
// endregion
|
||||||
|
|
||||||
// region cookie
|
// region cookie
|
||||||
@ -564,6 +614,8 @@ fn test_cookie_file() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Default::default(),
|
||||||
};
|
};
|
||||||
let mut client = Client::init(options);
|
let mut client = Client::init(options);
|
||||||
let request = default_get_request(
|
let request = default_get_request(
|
||||||
@ -589,6 +641,8 @@ fn test_proxy() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: 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 request = default_get_request("http://localhost:8000/hello".to_string());
|
||||||
|
@ -44,6 +44,8 @@ fn test_hurl_file() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Default::default(),
|
||||||
};
|
};
|
||||||
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")
|
||||||
@ -149,6 +151,8 @@ fn test_hello() {
|
|||||||
no_proxy: None,
|
no_proxy: None,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
insecure: false,
|
insecure: false,
|
||||||
|
timeout: Default::default(),
|
||||||
|
connect_timeout: Default::default(),
|
||||||
};
|
};
|
||||||
let mut client = http::Client::init(options);
|
let mut client = http::Client::init(options);
|
||||||
let source_info = SourceInfo {
|
let source_info = SourceInfo {
|
||||||
|
Loading…
Reference in New Issue
Block a user