null
@@ -329,7 +330,7 @@ Short description:
to-date-filter(used by filter)
to-float-filter(used by filter) toFloat
-
+
to-string-filter(used by filter) toString
url-decode-filter(used by filter) urlDecode
@@ -347,7 +348,7 @@ Short description:
sp(used by request, response, capture, assert, header-query, certificate-query, cookie-query, xpath-query, jsonpath-query, regex-query, variable-query, predicate, equal-predicate, not-equal-predicate, greater-predicate, greater-or-equal-predicate, less-predicate, less-or-equal-predicate, start-with-predicate, end-with-predicate, contain-predicate, match-predicate, include-predicate, expr, jsonpath-filter, nth-filter, regex-filter, replace-filter, split-filter, to-date-filter, url-query-param-filter, xpath-filter, lt) [ \t]
-
lt(used by hurl-file, request, response, header, body, query-string-params-section, form-params-section, multipart-form-data-section, cookies-section, captures-section, asserts-section, basic-auth-section, options-section, filename-param, capture, assert, option, aws-sigv4-option, ca-certificate-option, client-certificate-option, client-key-option, compressed-option, connect-to-option, connect-timeout-option, delay-option, follow-redirect-option, follow-redirect-trusted-option, header-option, http10-option, http11-option, http2-option, http3-option, insecure-option, ipv4-option, ipv6-option, limit-rate-option, max-redirs-option, netrc-option, netrc-file-option, netrc-optional-option, output-option, path-as-is-option, proxy-option, resolve-option, repeat-option, retry-option, retry-interval-option, skip-option, unix-socket-option, user-option, variable-option, verbose-option, very-verbose-option, multiline-string)
+
lt(used by hurl-file, request, response, header, body, query-string-params-section, form-params-section, multipart-form-data-section, cookies-section, captures-section, asserts-section, basic-auth-section, options-section, filename-param, capture, assert, option, aws-sigv4-option, ca-certificate-option, client-certificate-option, client-key-option, compressed-option, connect-to-option, connect-timeout-option, delay-option, follow-redirect-option, follow-redirect-trusted-option, header-option, http10-option, http11-option, http2-option, http3-option, insecure-option, ipv4-option, ipv6-option, limit-rate-option, max-redirs-option, max-time-option, netrc-option, netrc-file-option, netrc-optional-option, output-option, path-as-is-option, proxy-option, resolve-option, repeat-option, retry-option, retry-interval-option, skip-option, unix-socket-option, user-option, variable-option, verbose-option, very-verbose-option, multiline-string)
regex-content(used by regex)
diff --git a/docs/request.md b/docs/request.md
index da4b258cdb..99728c4288 100644
--- a/docs/request.md
+++ b/docs/request.md
@@ -215,6 +215,7 @@ ipv6: true # use IPv6 addresses
limit-rate: 32000 # limit this request to the specidied speed (bytes/s)
location: true # follow redirection for this request
max-redirs: 10 # maximum number of redirections
+max-time: 30s # maximum time for a request/response
output: out.html # dump the response to this file
path-as-is: true # do not handle sequences of /../ or /./ in URL path
retry: 10 # number of retry if HTTP/asserts errors
diff --git a/docs/spec/grammar/hurl.grammar b/docs/spec/grammar/hurl.grammar
index 630db9e0cc..1130c05132 100644
--- a/docs/spec/grammar/hurl.grammar
+++ b/docs/spec/grammar/hurl.grammar
@@ -136,6 +136,7 @@ option:
| ipv6-option
| limit-rate-option
| max-redirs-option
+ | max-time-option
| netrc-option
| netrc-file-option
| netrc-optional-option
@@ -194,6 +195,8 @@ limit-rate-option: "limit-rate" ":" integer-option lt
max-redirs-option: "max-redirs" ":" integer-option lt
+max-time-option: "max-time" ":" integer-option lt
+
netrc-option: "netrc" ":" boolean-option lt
netrc-file-option: "netrc-file" ":" value-string lt
diff --git a/integration/hurl/tests_error_parser/invalid_option.err b/integration/hurl/tests_error_parser/invalid_option.err
index 3af1b4ff8c..910c96415d 100644
--- a/integration/hurl/tests_error_parser/invalid_option.err
+++ b/integration/hurl/tests_error_parser/invalid_option.err
@@ -2,6 +2,6 @@ error: Parsing option
--> tests_error_parser/invalid_option.hurl:3:1
|
3 | foo: true
- | ^ the option name is not valid. Valid values are aws-sigv4, cacert, cert, compressed, connect-to, delay, insecure, header, http1.0, http1.1, http2, http3, ipv4, ipv6, key, location, max-redirs, output, path-as-is, proxy, redirects, resolve, retry, retry-interval, skip, unix-socket, variable, verbose, very-verbose
+ | ^ the option name is not valid. Valid values are aws-sigv4, cacert, cert, compressed, connect-to, delay, insecure, header, http1.0, http1.1, http2, http3, ipv4, ipv6, key, location, max-redirs, max-time, output, path-as-is, proxy, redirects, resolve, retry, retry-interval, skip, unix-socket, variable, verbose, very-verbose
|
diff --git a/integration/hurlfmt/tests_export/options.html b/integration/hurlfmt/tests_export/options.html
index cb0bc9f26d..4387aad909 100644
--- a/integration/hurlfmt/tests_export/options.html
+++ b/integration/hurlfmt/tests_export/options.html
@@ -23,6 +23,7 @@
ipv6: false
limit-rate: 1000
max-redirs: 10
+
max-time: 100s
netrc: false
netrc-file: netrcfile
netrc-optional: false
@@ -72,6 +73,7 @@
ipv6: {{ipv6}}
limit-rate: {{limit-rate}}
max-redirs: {{max-redirs}}
+
max-time: {{max-time}}
netrc: {{netrc}}
netrc-file: {{netrc-file}}
netrc-optional: {{netrc-optional}}
diff --git a/integration/hurlfmt/tests_export/options.hurl b/integration/hurlfmt/tests_export/options.hurl
index a7a146bbb7..2922744649 100644
--- a/integration/hurlfmt/tests_export/options.hurl
+++ b/integration/hurlfmt/tests_export/options.hurl
@@ -23,6 +23,7 @@ ipv4: false
ipv6: false
limit-rate: 1000
max-redirs: 10
+max-time: 100s
netrc: false
netrc-file: netrcfile
netrc-optional: false
@@ -72,6 +73,7 @@ ipv4: {{ipv4}}
ipv6: {{ipv6}}
limit-rate: {{limit-rate}}
max-redirs: {{max-redirs}}
+max-time: {{max-time}}
netrc: {{netrc}}
netrc-file: {{netrc-file}}
netrc-optional: {{netrc-optional}}
diff --git a/integration/hurlfmt/tests_export/options.json b/integration/hurlfmt/tests_export/options.json
index 9b571f9cfb..c13b8bd568 100644
--- a/integration/hurlfmt/tests_export/options.json
+++ b/integration/hurlfmt/tests_export/options.json
@@ -1 +1 @@
-{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/hello","options":[{"name":"aws-sigv4","value":"aws:amz:eu-central-1:sts"},{"name":"cacert","value":"cacertfile"},{"name":"cert","value":"certfile"},{"name":"cert","value":"certfile:qU114@q,[\"NO"},{"name":"key","value":"keyfile"},{"name":"compressed","value":false},{"name":"connect-to","value":"example.com:443:example.net:8443"},{"value":60,"unit":"s","name":"connect-timeout"},{"name":"delay","value":1000},{"value":1000,"unit":"ms","name":"delay"},{"value":1,"unit":"s","name":"delay"},{"name":"location","value":false},{"name":"location-trusted","value":false},{"name":"header","value":"key: value"},{"name":"http1.0","value":false},{"name":"http1.1","value":false},{"name":"http2","value":false},{"name":"http3","value":false},{"name":"insecure","value":false},{"name":"ipv4","value":false},{"name":"ipv6","value":false},{"name":"limit-rate","value":1000},{"name":"max-redirs","value":10},{"name":"netrc","value":false},{"name":"netrc-file","value":"netrcfile"},{"name":"netrc-optional","value":false},{"name":"output","value":"output.txt"},{"name":"path-as-is","value":false},{"name":"proxy","value":"http://proxy.example"},{"name":"repeat","value":-1},{"name":"repeat","value":5},{"name":"resolve","value":"example.com:443:127.0.0.1"},{"name":"retry","value":0},{"name":"retry","value":-1},{"name":"retry","value":4},{"name":"retry-interval","value":1000},{"value":1000,"unit":"ms","name":"retry-interval"},{"value":1,"unit":"s","name":"retry-interval"},{"name":"skip","value":false},{"name":"unix-socket","value":"build/unix_socket.sock"},{"name":"user","value":"bob:secret"},{"name":"variable","value":"user=null"},{"name":"variable","value":"status=true"},{"name":"variable","value":"count=2"},{"name":"variable","value":"score=7.7"},{"name":"variable","value":"name=Bob"},{"name":"variable","value":"name=Bob"},{"name":"verbose","value":false},{"name":"very-verbose","value":false}]}},{"request":{"method":"GET","url":"http://localhost:8000/hello","options":[{"name":"aws-sigv4","value":"{{aws-sigv4}}"},{"name":"cacert","value":"{{cacert}}"},{"name":"cert","value":"{{cert}}"},{"name":"key","value":"{{key}}"},{"name":"compressed","value":"{{compressed}}"},{"name":"connect-to","value":"{{connect-to}}"},{"name":"connect-timeout","value":"{{connect-timeout}}"},{"name":"delay","value":"{{delay}}"},{"name":"location","value":"{{location}}"},{"name":"location-trusted","value":"{{location-trusted}}"},{"name":"header","value":"{{header}}"},{"name":"http1.0","value":"{{http10}}"},{"name":"http1.1","value":"{{http11}}"},{"name":"http2","value":"{{http2}}"},{"name":"http3","value":"{{http3}}"},{"name":"insecure","value":"{{insecure}}"},{"name":"ipv4","value":"{{ipv4}}"},{"name":"ipv6","value":"{{ipv6}}"},{"name":"limit-rate","value":"{{limit-rate}}"},{"name":"max-redirs","value":"{{max-redirs}}"},{"name":"netrc","value":"{{netrc}}"},{"name":"netrc-file","value":"{{netrc-file}}"},{"name":"netrc-optional","value":"{{netrc-optional}}"},{"name":"output","value":"{{output}}"},{"name":"path-as-is","value":"{{path-as-is}}"},{"name":"proxy","value":"{{proxy}}"},{"name":"repeat","value":"{{repeat}}"},{"name":"resolve","value":"{{resolve}}"},{"name":"retry","value":"{{retry}}"},{"name":"retry-interval","value":"{{retry-interval}}"},{"name":"skip","value":"{{skip}}"},{"name":"unix-socket","value":"{{socket-file}}"},{"name":"user","value":"{{user}}"},{"name":"verbose","value":"{{verbose}}"},{"name":"very-verbose","value":"{{very-verbose}}"}]}}]}
+{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/hello","options":[{"name":"aws-sigv4","value":"aws:amz:eu-central-1:sts"},{"name":"cacert","value":"cacertfile"},{"name":"cert","value":"certfile"},{"name":"cert","value":"certfile:qU114@q,[\"NO"},{"name":"key","value":"keyfile"},{"name":"compressed","value":false},{"name":"connect-to","value":"example.com:443:example.net:8443"},{"value":60,"unit":"s","name":"connect-timeout"},{"name":"delay","value":1000},{"value":1000,"unit":"ms","name":"delay"},{"value":1,"unit":"s","name":"delay"},{"name":"location","value":false},{"name":"location-trusted","value":false},{"name":"header","value":"key: value"},{"name":"http1.0","value":false},{"name":"http1.1","value":false},{"name":"http2","value":false},{"name":"http3","value":false},{"name":"insecure","value":false},{"name":"ipv4","value":false},{"name":"ipv6","value":false},{"name":"limit-rate","value":1000},{"name":"max-redirs","value":10},{"value":100,"unit":"s","name":"max-time"},{"name":"netrc","value":false},{"name":"netrc-file","value":"netrcfile"},{"name":"netrc-optional","value":false},{"name":"output","value":"output.txt"},{"name":"path-as-is","value":false},{"name":"proxy","value":"http://proxy.example"},{"name":"repeat","value":-1},{"name":"repeat","value":5},{"name":"resolve","value":"example.com:443:127.0.0.1"},{"name":"retry","value":0},{"name":"retry","value":-1},{"name":"retry","value":4},{"name":"retry-interval","value":1000},{"value":1000,"unit":"ms","name":"retry-interval"},{"value":1,"unit":"s","name":"retry-interval"},{"name":"skip","value":false},{"name":"unix-socket","value":"build/unix_socket.sock"},{"name":"user","value":"bob:secret"},{"name":"variable","value":"user=null"},{"name":"variable","value":"status=true"},{"name":"variable","value":"count=2"},{"name":"variable","value":"score=7.7"},{"name":"variable","value":"name=Bob"},{"name":"variable","value":"name=Bob"},{"name":"verbose","value":false},{"name":"very-verbose","value":false}]}},{"request":{"method":"GET","url":"http://localhost:8000/hello","options":[{"name":"aws-sigv4","value":"{{aws-sigv4}}"},{"name":"cacert","value":"{{cacert}}"},{"name":"cert","value":"{{cert}}"},{"name":"key","value":"{{key}}"},{"name":"compressed","value":"{{compressed}}"},{"name":"connect-to","value":"{{connect-to}}"},{"name":"connect-timeout","value":"{{connect-timeout}}"},{"name":"delay","value":"{{delay}}"},{"name":"location","value":"{{location}}"},{"name":"location-trusted","value":"{{location-trusted}}"},{"name":"header","value":"{{header}}"},{"name":"http1.0","value":"{{http10}}"},{"name":"http1.1","value":"{{http11}}"},{"name":"http2","value":"{{http2}}"},{"name":"http3","value":"{{http3}}"},{"name":"insecure","value":"{{insecure}}"},{"name":"ipv4","value":"{{ipv4}}"},{"name":"ipv6","value":"{{ipv6}}"},{"name":"limit-rate","value":"{{limit-rate}}"},{"name":"max-redirs","value":"{{max-redirs}}"},{"name":"max-time","value":"{{max-time}}"},{"name":"netrc","value":"{{netrc}}"},{"name":"netrc-file","value":"{{netrc-file}}"},{"name":"netrc-optional","value":"{{netrc-optional}}"},{"name":"output","value":"{{output}}"},{"name":"path-as-is","value":"{{path-as-is}}"},{"name":"proxy","value":"{{proxy}}"},{"name":"repeat","value":"{{repeat}}"},{"name":"resolve","value":"{{resolve}}"},{"name":"retry","value":"{{retry}}"},{"name":"retry-interval","value":"{{retry-interval}}"},{"name":"skip","value":"{{skip}}"},{"name":"unix-socket","value":"{{socket-file}}"},{"name":"user","value":"{{user}}"},{"name":"verbose","value":"{{verbose}}"},{"name":"very-verbose","value":"{{very-verbose}}"}]}}]}
diff --git a/integration/hurlfmt/tests_export/options.lint.hurl b/integration/hurlfmt/tests_export/options.lint.hurl
index 8d2e8557e2..2e9836f5c6 100644
--- a/integration/hurlfmt/tests_export/options.lint.hurl
+++ b/integration/hurlfmt/tests_export/options.lint.hurl
@@ -23,6 +23,7 @@ ipv4: false
ipv6: false
limit-rate: 1000
max-redirs: 10
+max-time: 100s
netrc: false
netrc-file: netrcfile
netrc-optional: false
@@ -72,6 +73,7 @@ ipv4: {{ipv4}}
ipv6: {{ipv6}}
limit-rate: {{limit-rate}}
max-redirs: {{max-redirs}}
+max-time: {{max-time}}
netrc: {{netrc}}
netrc-file: {{netrc-file}}
netrc-optional: {{netrc-optional}}
diff --git a/packages/hurl/src/runner/options.rs b/packages/hurl/src/runner/options.rs
index 4de66e0f7e..9db448c87b 100644
--- a/packages/hurl/src/runner/options.rs
+++ b/packages/hurl/src/runner/options.rs
@@ -200,6 +200,11 @@ pub fn get_entry_options(
let value = eval_count_option(value, variables)?;
entry_options.max_redirect = value;
}
+ OptionKind::MaxTime(value) => {
+ let value =
+ eval_duration_option(value, variables, DurationUnit::MilliSecond)?;
+ entry_options.timeout = value;
+ }
OptionKind::NetRc(value) => {
let value = eval_boolean_option(value, variables)?;
entry_options.netrc = value;
diff --git a/packages/hurl_core/src/ast/option.rs b/packages/hurl_core/src/ast/option.rs
index 3c69b0106e..50b1ba6dfc 100644
--- a/packages/hurl_core/src/ast/option.rs
+++ b/packages/hurl_core/src/ast/option.rs
@@ -54,6 +54,7 @@ pub enum OptionKind {
FollowLocationTrusted(BooleanOption),
LimitRate(NaturalOption),
MaxRedirect(CountOption),
+ MaxTime(DurationOption),
NetRc(BooleanOption),
NetRcFile(Template),
NetRcOptional(BooleanOption),
@@ -96,6 +97,7 @@ impl OptionKind {
OptionKind::IpV6(_) => "ipv6",
OptionKind::LimitRate(_) => "limit-rate",
OptionKind::MaxRedirect(_) => "max-redirs",
+ OptionKind::MaxTime(_) => "max-time",
OptionKind::NetRc(_) => "netrc",
OptionKind::NetRcFile(_) => "netrc-file",
OptionKind::NetRcOptional(_) => "netrc-optional",
@@ -139,6 +141,7 @@ impl fmt::Display for OptionKind {
OptionKind::IpV6(value) => value.to_string(),
OptionKind::LimitRate(value) => value.to_string(),
OptionKind::MaxRedirect(value) => value.to_string(),
+ OptionKind::MaxTime(value) => value.to_string(),
OptionKind::NetRc(value) => value.to_string(),
OptionKind::NetRcFile(filename) => filename.to_string(),
OptionKind::NetRcOptional(value) => value.to_string(),
diff --git a/packages/hurl_core/src/format/html.rs b/packages/hurl_core/src/format/html.rs
index c412d6b9bf..b2cd222ffe 100644
--- a/packages/hurl_core/src/format/html.rs
+++ b/packages/hurl_core/src/format/html.rs
@@ -239,6 +239,7 @@ impl HtmlFormatter {
OptionKind::IpV6(value) => self.fmt_bool_option(value),
OptionKind::LimitRate(value) => self.fmt_natural_option(value),
OptionKind::MaxRedirect(value) => self.fmt_count_option(value),
+ OptionKind::MaxTime(value) => self.fmt_duration_option(value),
OptionKind::NetRc(value) => self.fmt_bool_option(value),
OptionKind::NetRcFile(filename) => self.fmt_filename(filename),
OptionKind::NetRcOptional(value) => self.fmt_bool_option(value),
diff --git a/packages/hurl_core/src/parser/error.rs b/packages/hurl_core/src/parser/error.rs
index 30f95c5042..baab0d78a4 100644
--- a/packages/hurl_core/src/parser/error.rs
+++ b/packages/hurl_core/src/parser/error.rs
@@ -173,6 +173,7 @@ impl DisplaySourceError for ParseError {
"key",
"location",
"max-redirs",
+ "max-time",
"output",
"path-as-is",
"proxy",
diff --git a/packages/hurl_core/src/parser/option.rs b/packages/hurl_core/src/parser/option.rs
index 3ecf053b9d..39d138d20b 100644
--- a/packages/hurl_core/src/parser/option.rs
+++ b/packages/hurl_core/src/parser/option.rs
@@ -66,6 +66,7 @@ pub fn parse(reader: &mut Reader) -> ParseResult
{
"location" => option_follow_location(reader)?,
"location-trusted" => option_follow_location_trusted(reader)?,
"max-redirs" => option_max_redirect(reader)?,
+ "max-time" => option_max_time(reader)?,
"netrc" => option_netrc(reader)?,
"netrc-file" => option_netrc_file(reader)?,
"netrc-optional" => option_netrc_optional(reader)?,
@@ -202,6 +203,11 @@ fn option_max_redirect(reader: &mut Reader) -> ParseResult {
Ok(OptionKind::MaxRedirect(value))
}
+fn option_max_time(reader: &mut Reader) -> ParseResult {
+ let value = duration_option(reader)?;
+ Ok(OptionKind::MaxTime(value))
+}
+
fn option_netrc(reader: &mut Reader) -> ParseResult {
let value = non_recover(boolean_option, reader)?;
Ok(OptionKind::NetRc(value))
diff --git a/packages/hurlfmt/src/format/json.rs b/packages/hurlfmt/src/format/json.rs
index 4d2929f454..fdef228889 100644
--- a/packages/hurlfmt/src/format/json.rs
+++ b/packages/hurlfmt/src/format/json.rs
@@ -327,6 +327,7 @@ impl ToJson for EntryOption {
OptionKind::IpV6(value) => value.to_json(),
OptionKind::LimitRate(value) => value.to_json(),
OptionKind::MaxRedirect(value) => value.to_json(),
+ OptionKind::MaxTime(value) => value.to_json(),
OptionKind::NetRc(value) => value.to_json(),
OptionKind::NetRcFile(filename) => JValue::String(filename.to_string()),
OptionKind::NetRcOptional(value) => value.to_json(),
diff --git a/packages/hurlfmt/src/format/token.rs b/packages/hurlfmt/src/format/token.rs
index cb53a95bcc..e5eb98c381 100644
--- a/packages/hurlfmt/src/format/token.rs
+++ b/packages/hurlfmt/src/format/token.rs
@@ -915,6 +915,7 @@ impl Tokenizable for OptionKind {
OptionKind::IpV6(value) => value.tokenize(),
OptionKind::LimitRate(value) => value.tokenize(),
OptionKind::MaxRedirect(value) => value.tokenize(),
+ OptionKind::MaxTime(value) => value.tokenize(),
OptionKind::NetRc(value) => value.tokenize(),
OptionKind::NetRcFile(filename) => filename.tokenize(),
OptionKind::NetRcOptional(value) => value.tokenize(),