mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-08-15 16:40:29 +03:00
Apply delay only once per entry, no matter how many retry.
This commit is contained in:
parent
438fbf721a
commit
90bb395bae
@ -1,17 +1,17 @@
|
||||
<mxfile host="app.diagrams.net" modified="2024-06-18T11:11:48.851Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.15" etag="JIFONLN-45vT0ClTlasG" version="24.5.5" type="device">
|
||||
<mxfile host="app.diagrams.net" modified="2024-06-18T14:42:17.996Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.15" etag="q-OuEenRq_H6SQyWZ8w5" version="24.5.5" type="device">
|
||||
<diagram name="Page-1" id="Xiz49D0FumDPF5wHgXgK">
|
||||
<mxGraphModel dx="2020" dy="1139" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2000" pageHeight="2000" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-5" value="<b>START</b>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;fillColor=none;strokeColor=#FF0288;fillStyle=auto;fontColor=#FF0288;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="90" width="80" height="40" as="geometry" />
|
||||
<mxGeometry x="360" y="100" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-7" value="Entry&nbsp;<div>to run?</div>" style="strokeWidth=0;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;spacingTop=-3;fillColor=#CCFF66;strokeColor=none;fontStyle=0" vertex="1" parent="1">
|
||||
<mxGeometry x="350" y="170" width="100" height="80" as="geometry" />
|
||||
<mxGeometry x="350" y="180" width="100" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-11" value="<font color="#6c8ebf">Eval</font><div><font color="#6c8ebf">entry options</font></div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=0;arcSize=18;labelBorderColor=none;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="350" y="290" width="100" height="50" as="geometry" />
|
||||
<mxGeometry x="350" y="300" width="100" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-12" value="" style="endArrow=block;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;endFill=1;" edge="1" parent="1" source="rCkY846AgjEdWc3Gds_q-5" target="rCkY846AgjEdWc3Gds_q-7">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
@ -31,7 +31,7 @@
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-15" value="<b>SUCCESS</b>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;fillColor=none;strokeColor=#FF0288;fillStyle=auto;fontColor=#FF0288;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="190" width="80" height="40" as="geometry" />
|
||||
<mxGeometry x="220" y="200" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-16" value="" style="endArrow=block;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;endFill=1;dashed=1;" edge="1" parent="1" source="rCkY846AgjEdWc3Gds_q-7" target="rCkY846AgjEdWc3Gds_q-15">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
@ -68,7 +68,7 @@
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-23" value="<font color="#6c8ebf"><span style="caret-color: rgb(108, 142, 191);">Sleep delay</span></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=0;arcSize=18;labelBorderColor=none;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="200" y="600" width="100" height="40" as="geometry" />
|
||||
<mxGeometry x="200" y="600" width="100" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="rCkY846AgjEdWc3Gds_q-25" value="" style="endArrow=block;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;endFill=1;exitX=0.2;exitY=0.75;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="rCkY846AgjEdWc3Gds_q-20" target="rCkY846AgjEdWc3Gds_q-23">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@ -26,7 +26,7 @@ def main():
|
||||
+ get_files("tests_failed/*." + extension)
|
||||
+ get_files("tests_failed_not_linted/*." + extension)
|
||||
+ get_files("tests_error_parser/*." + extension)
|
||||
+ get_files("ssl/*." + extension)
|
||||
# + get_files("ssl/*." + extension)
|
||||
)
|
||||
for f in sorted(script_files):
|
||||
test_script.test(f)
|
||||
|
@ -42,10 +42,6 @@
|
||||
* ------------------------------------------------------------------------------
|
||||
* Executing entry 1
|
||||
*
|
||||
* Entry options:
|
||||
* retry: 2
|
||||
* retry-interval: 0
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
* Request:
|
||||
@ -83,10 +79,6 @@
|
||||
* ------------------------------------------------------------------------------
|
||||
* Executing entry 1
|
||||
*
|
||||
* Entry options:
|
||||
* retry: 2
|
||||
* retry-interval: 0
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
* Request:
|
||||
|
@ -31,7 +31,7 @@
|
||||
* Entry options:
|
||||
* delay: 1000
|
||||
*
|
||||
* Delay entry 2 (x1 by 1000 ms)
|
||||
* Delay entry 2 (pause 1000 ms)
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Entry options:
|
||||
* delay: 5000
|
||||
*
|
||||
* Delay entry 1 (x1 by 5000 ms)
|
||||
* Delay entry 1 (pause 5000 ms)
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
@ -41,7 +41,7 @@
|
||||
* Entry options:
|
||||
* delay: 5000
|
||||
*
|
||||
* Delay entry 1 (x1 by 5000 ms)
|
||||
* Delay entry 1 (pause 5000 ms)
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
@ -75,7 +75,7 @@
|
||||
* Entry options:
|
||||
* delay: 5000
|
||||
*
|
||||
* Delay entry 1 (x1 by 5000 ms)
|
||||
* Delay entry 1 (pause 5000 ms)
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
@ -109,7 +109,7 @@
|
||||
* Entry options:
|
||||
* delay: 5000
|
||||
*
|
||||
* Delay entry 1 (x1 by 5000 ms)
|
||||
* Delay entry 1 (pause 5000 ms)
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
|
@ -72,10 +72,6 @@
|
||||
* ------------------------------------------------------------------------------
|
||||
* Executing entry 2
|
||||
*
|
||||
* Entry options:
|
||||
* retry: 10
|
||||
* retry-interval: 100
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
* Request:
|
||||
@ -114,10 +110,6 @@
|
||||
* ------------------------------------------------------------------------------
|
||||
* Executing entry 2
|
||||
*
|
||||
* Entry options:
|
||||
* retry: 10
|
||||
* retry-interval: 100
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
* Request:
|
||||
@ -156,10 +148,6 @@
|
||||
* ------------------------------------------------------------------------------
|
||||
* Executing entry 2
|
||||
*
|
||||
* Entry options:
|
||||
* retry: 10
|
||||
* retry-interval: 100
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
* Request:
|
||||
@ -198,10 +186,6 @@
|
||||
* ------------------------------------------------------------------------------
|
||||
* Executing entry 2
|
||||
*
|
||||
* Entry options:
|
||||
* retry: 10
|
||||
* retry-interval: 100
|
||||
*
|
||||
* Cookie store:
|
||||
*
|
||||
* Request:
|
||||
|
@ -142,7 +142,10 @@ def test_stderr(f, result):
|
||||
actual = ignore_lines(decode_string(result.stderr))
|
||||
if actual != expected:
|
||||
print(">>> error in stderr")
|
||||
print(f"actual: <{actual}>\nexpected: <{expected}>")
|
||||
print("actual:")
|
||||
print(actual)
|
||||
print("expected:")
|
||||
print(expected)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
@ -140,7 +140,6 @@ pub fn run_entries(
|
||||
let mut variables = variables.clone();
|
||||
let mut entry_index = runner_options.from_entry.unwrap_or(1);
|
||||
let n = runner_options.to_entry.unwrap_or(entries.len());
|
||||
let mut retry_count = 1;
|
||||
let default_verbosity = logger.verbosity;
|
||||
let start = Instant::now();
|
||||
let timestamp = Utc::now().timestamp();
|
||||
@ -151,6 +150,7 @@ pub fn run_entries(
|
||||
// The `entry_index` is not always incremented of each loop tick: an entry can be retried upon
|
||||
// errors for instance. Each entry is executed with options that are computed from the global
|
||||
// runner options and the "overridden" request options.
|
||||
// See <docs/spec/runner/run_cycle.md>
|
||||
loop {
|
||||
if entry_index > n {
|
||||
break;
|
||||
@ -173,120 +173,74 @@ pub fn run_entries(
|
||||
logger.verbosity = entry_verbosity;
|
||||
}
|
||||
|
||||
logger.debug_important(
|
||||
"------------------------------------------------------------------------------",
|
||||
);
|
||||
logger.debug_important(&format!("Executing entry {entry_index}"));
|
||||
log_run_entry(entry_index, logger);
|
||||
|
||||
warn_deprecated(entry, logger);
|
||||
|
||||
// We can report the progression of the run for --test mode.
|
||||
if let Some(listener) = listener {
|
||||
listener.on_running(entry_index - 1, n);
|
||||
}
|
||||
|
||||
// The real execution of the entry happens here, with the overridden entry options.
|
||||
// The real execution of the entry happens here, first: we compute the overridden request
|
||||
// options.
|
||||
let options = options::get_entry_options(entry, runner_options, &mut variables, logger);
|
||||
let mut entry_result = match &options {
|
||||
Err(error) => EntryResult {
|
||||
if let Err(error) = &options {
|
||||
// If we have error evaluating request options, we consider it as a non retryable error
|
||||
// and either break the runner or go to the next entries.
|
||||
let entry_result = EntryResult {
|
||||
entry_index,
|
||||
source_info: entry.source_info(),
|
||||
errors: vec![error.clone()],
|
||||
..Default::default()
|
||||
},
|
||||
Ok(options) => {
|
||||
if options.skip {
|
||||
logger.debug("");
|
||||
logger.debug_important(&format!("Entry {entry_index} has been skipped"));
|
||||
entry_index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let delay = options.delay;
|
||||
let delay_ms = delay.as_millis();
|
||||
if delay_ms > 0 {
|
||||
logger.debug("");
|
||||
logger.debug_important(&format!(
|
||||
"Delay entry {entry_index} (x{retry_count} by {delay_ms} ms)"
|
||||
));
|
||||
thread::sleep(delay);
|
||||
};
|
||||
|
||||
entry::run(
|
||||
entry,
|
||||
entry_index,
|
||||
&mut http_client,
|
||||
&mut variables,
|
||||
options,
|
||||
logger,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
// Check if we need to retry.
|
||||
let mut has_error = !entry_result.errors.is_empty();
|
||||
let (retry_opts, retry_interval) = match &options {
|
||||
Ok(options) => (options.retry, options.retry_interval),
|
||||
Err(_) => (runner_options.retry, runner_options.retry_interval),
|
||||
};
|
||||
// The retry threshold can only reached with a finite positive number of retries
|
||||
let retry_max_reached = if let Retry::Finite(r) = retry_opts {
|
||||
retry_count > r
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// If `retry_max_reached` is true, we print now a warning, before displaying any assert
|
||||
// error so any potential error is the last thing displayed to the user.
|
||||
// If `retry_max_reached` is not true (for instance `retry`is true, or there is no error
|
||||
// we first log the error and a potential warning about retrying.
|
||||
if retry_max_reached {
|
||||
logger.debug_important("Retry max count reached, no more retry");
|
||||
logger.debug("");
|
||||
}
|
||||
|
||||
// We logs eventual errors, only if we're not retrying the current entry...
|
||||
// The retry does not take into account a possible output Error
|
||||
let retry = !matches!(retry_opts, Retry::None) && !retry_max_reached && has_error;
|
||||
|
||||
// When --output is overridden on a request level, we output the HTTP response only if the
|
||||
// call has succeeded.
|
||||
if let Ok(RunnerOptions {
|
||||
output: Some(output),
|
||||
..
|
||||
}) = options
|
||||
{
|
||||
if !has_error {
|
||||
let source_info = get_output_source_info(entry);
|
||||
if let Err(error) = entry_result.write_response(
|
||||
&output,
|
||||
&runner_options.context_dir,
|
||||
stdout,
|
||||
source_info,
|
||||
) {
|
||||
entry_result.errors.push(error);
|
||||
has_error = true;
|
||||
}
|
||||
};
|
||||
log_errors(&entry_result, content, false, logger);
|
||||
entries_result.push(entry_result);
|
||||
if runner_options.continue_on_error {
|
||||
entry_index += 1;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if has_error {
|
||||
log_errors(&entry_result, content, retry, logger);
|
||||
}
|
||||
entries_result.push(entry_result);
|
||||
let options = options.unwrap();
|
||||
|
||||
if retry {
|
||||
let delay = retry_interval.as_millis();
|
||||
// Should we skip?
|
||||
if options.skip {
|
||||
logger.debug("");
|
||||
logger.debug_important(&format!(
|
||||
"Retry entry {entry_index} (x{retry_count} pause {delay} ms)"
|
||||
));
|
||||
retry_count += 1;
|
||||
// If we retry the entry, we do not want to display a 'blank' progress bar during the
|
||||
// sleep delay. During the pause, we artificially show the previously erased progress
|
||||
// line.
|
||||
thread::sleep(retry_interval);
|
||||
logger.debug_important(&format!("Entry {entry_index} has been skipped"));
|
||||
entry_index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Should we delay?
|
||||
let delay = options.delay;
|
||||
let delay_ms = delay.as_millis();
|
||||
if delay_ms > 0 {
|
||||
logger.debug("");
|
||||
logger.debug_important(&format!("Delay entry {entry_index} (pause {delay_ms} ms)"));
|
||||
thread::sleep(delay);
|
||||
};
|
||||
|
||||
// Loop for executing HTTP run requests, with optional retry. Only "HTTP" errors in options
|
||||
// are taken into account for retry (errors while computing entry options and output error
|
||||
// are not retried).
|
||||
let results = run_request(
|
||||
entry,
|
||||
entry_index,
|
||||
content,
|
||||
&mut http_client,
|
||||
&options,
|
||||
&mut variables,
|
||||
stdout,
|
||||
logger,
|
||||
);
|
||||
|
||||
let has_error = results.last().map_or(false, |r| !r.errors.is_empty());
|
||||
|
||||
entries_result.extend(results);
|
||||
|
||||
if let Some(post_entry) = runner_options.post_entry {
|
||||
let exit = post_entry();
|
||||
if exit {
|
||||
@ -299,7 +253,6 @@ pub fn run_entries(
|
||||
|
||||
// We pass to the next entry
|
||||
entry_index += 1;
|
||||
retry_count = 1;
|
||||
}
|
||||
|
||||
let time_in_ms = start.elapsed().as_millis();
|
||||
@ -314,6 +267,90 @@ pub fn run_entries(
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs an HTTP request and optional retry it until there are no HTTP errors. Returns a list of
|
||||
/// [`EntryResult`].
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn run_request(
|
||||
entry: &Entry,
|
||||
entry_index: usize,
|
||||
content: &str,
|
||||
http_client: &mut Client,
|
||||
options: &RunnerOptions,
|
||||
variables: &mut HashMap<String, Value>,
|
||||
stdout: &mut Stdout,
|
||||
logger: &mut Logger,
|
||||
) -> Vec<EntryResult> {
|
||||
let mut results = vec![];
|
||||
let mut retry_count = 1;
|
||||
|
||||
loop {
|
||||
let mut result = entry::run(entry, entry_index, http_client, variables, options, logger);
|
||||
|
||||
// Check if we need to retry.
|
||||
let mut has_error = !result.errors.is_empty();
|
||||
|
||||
// The retry threshold can only be reached with a finite positive number of retries
|
||||
let retry_max_reached = if let Retry::Finite(r) = options.retry {
|
||||
retry_count > r
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// If `retry_max_reached` is true, we print now a warning, before displaying any assert
|
||||
// error so any potential error is the last thing displayed to the user.
|
||||
// If `retry_max_reached` is not true (for instance `retry`is true, or there is no error
|
||||
// we first log the error and a potential warning about retrying.
|
||||
if retry_max_reached {
|
||||
logger.debug_important("Retry max count reached, no more retry");
|
||||
logger.debug("");
|
||||
}
|
||||
|
||||
// We log eventual errors, only if we're not retrying the current entry...
|
||||
// The retry does not take into account a possible output Error
|
||||
let retry = !matches!(options.retry, Retry::None) && !retry_max_reached && has_error;
|
||||
|
||||
// When --output is overridden on a request level, we output the HTTP response only if the
|
||||
// call has succeeded. Output errors are not taken into account for retrying requests.
|
||||
if let Some(output) = &options.output {
|
||||
if !has_error {
|
||||
let source_info = get_output_source_info(entry);
|
||||
if let Err(error) =
|
||||
result.write_response(output, &options.context_dir, stdout, source_info)
|
||||
{
|
||||
result.errors.push(error);
|
||||
has_error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_error {
|
||||
log_errors(&result, content, retry, logger);
|
||||
}
|
||||
results.push(result);
|
||||
|
||||
// No retry, we leave the HTTP run requests loop.
|
||||
if !retry {
|
||||
break;
|
||||
}
|
||||
|
||||
let delay = options.retry_interval.as_millis();
|
||||
logger.debug("");
|
||||
logger.debug_important(&format!(
|
||||
"Retry entry {entry_index} (x{retry_count} pause {delay} ms)"
|
||||
));
|
||||
retry_count += 1;
|
||||
// If we retry the entry, we do not want to display a 'blank' progress bar during the
|
||||
// sleep delay. During the pause, we artificially show the previously erased progress
|
||||
// line.
|
||||
thread::sleep(options.retry_interval);
|
||||
|
||||
// TODO: We keep this log because we don't want to change stderr with the changes
|
||||
// introduced by <https://github.com/Orange-OpenSource/hurl/issues/1973>
|
||||
log_run_entry(entry_index, logger);
|
||||
}
|
||||
|
||||
results
|
||||
}
|
||||
|
||||
/// Use source_info from output option if this option has been defined
|
||||
fn get_output_source_info(entry: &Entry) -> SourceInfo {
|
||||
let mut source_info = entry.source_info();
|
||||
@ -509,6 +546,14 @@ fn log_errors(entry_result: &EntryResult, content: &str, retry: bool, logger: &m
|
||||
.for_each(|error| logger.error_runtime_rich(content, error, entry_result.source_info));
|
||||
}
|
||||
|
||||
/// Logs the header indicating the begin of the entry run.
|
||||
fn log_run_entry(entry_index: usize, logger: &mut Logger) {
|
||||
logger.debug_important(
|
||||
"------------------------------------------------------------------------------",
|
||||
);
|
||||
logger.debug_important(&format!("Executing entry {entry_index}"));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -41,12 +41,12 @@ pub fn get_entry_options(
|
||||
// When used globally (on the command line), `--output` writes the last successful request
|
||||
// to `output` file. We don't want to output every entry's response, so we initialise
|
||||
// output to `None`.
|
||||
let mut runner_options = RunnerOptions {
|
||||
let mut entry_options = RunnerOptions {
|
||||
output: None,
|
||||
..runner_options
|
||||
};
|
||||
if !has_options(entry) {
|
||||
return Ok(runner_options);
|
||||
return Ok(entry_options);
|
||||
}
|
||||
|
||||
logger.debug("");
|
||||
@ -58,31 +58,31 @@ pub fn get_entry_options(
|
||||
match &option.kind {
|
||||
OptionKind::AwsSigV4(value) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
runner_options.aws_sigv4 = Some(value);
|
||||
entry_options.aws_sigv4 = Some(value);
|
||||
}
|
||||
OptionKind::CaCertificate(filename) => {
|
||||
let value = eval_template(filename, variables)?;
|
||||
runner_options.cacert_file = Some(value);
|
||||
entry_options.cacert_file = Some(value);
|
||||
}
|
||||
OptionKind::ClientCert(filename) => {
|
||||
let value = eval_template(filename, variables)?;
|
||||
runner_options.client_cert_file = Some(value);
|
||||
entry_options.client_cert_file = Some(value);
|
||||
}
|
||||
OptionKind::ClientKey(filename) => {
|
||||
let value = eval_template(filename, variables)?;
|
||||
runner_options.client_key_file = Some(value);
|
||||
entry_options.client_key_file = Some(value);
|
||||
}
|
||||
OptionKind::Compressed(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.compressed = value;
|
||||
entry_options.compressed = value;
|
||||
}
|
||||
OptionKind::ConnectTo(value) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
runner_options.connects_to.push(value);
|
||||
entry_options.connects_to.push(value);
|
||||
}
|
||||
OptionKind::Delay(value) => {
|
||||
let value = eval_natural_option(value, variables)?;
|
||||
runner_options.delay = Duration::from_millis(value);
|
||||
entry_options.delay = Duration::from_millis(value);
|
||||
}
|
||||
// HTTP version options (such as http1.0, http1.1, http2 etc...) are activated
|
||||
// through a flag. In an `[Options]` section, the signification of such a flag is:
|
||||
@ -111,51 +111,51 @@ pub fn get_entry_options(
|
||||
OptionKind::Http10(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
if value {
|
||||
runner_options.http_version = RequestedHttpVersion::Http10;
|
||||
entry_options.http_version = RequestedHttpVersion::Http10;
|
||||
}
|
||||
}
|
||||
OptionKind::Http11(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
if value {
|
||||
runner_options.http_version = RequestedHttpVersion::Http11;
|
||||
entry_options.http_version = RequestedHttpVersion::Http11;
|
||||
} else {
|
||||
runner_options.http_version = RequestedHttpVersion::Http10;
|
||||
entry_options.http_version = RequestedHttpVersion::Http10;
|
||||
}
|
||||
}
|
||||
OptionKind::Http2(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
if value {
|
||||
runner_options.http_version = RequestedHttpVersion::Http2;
|
||||
entry_options.http_version = RequestedHttpVersion::Http2;
|
||||
} else {
|
||||
runner_options.http_version = RequestedHttpVersion::Http11;
|
||||
entry_options.http_version = RequestedHttpVersion::Http11;
|
||||
}
|
||||
}
|
||||
OptionKind::Http3(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
if value {
|
||||
runner_options.http_version = RequestedHttpVersion::Http3;
|
||||
entry_options.http_version = RequestedHttpVersion::Http3;
|
||||
} else {
|
||||
runner_options.http_version = RequestedHttpVersion::Http2;
|
||||
entry_options.http_version = RequestedHttpVersion::Http2;
|
||||
}
|
||||
}
|
||||
OptionKind::FollowLocation(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.follow_location = value;
|
||||
entry_options.follow_location = value;
|
||||
}
|
||||
OptionKind::FollowLocationTrusted(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
if value {
|
||||
runner_options.follow_location = true;
|
||||
entry_options.follow_location = true;
|
||||
}
|
||||
runner_options.follow_location_trusted = value;
|
||||
entry_options.follow_location_trusted = value;
|
||||
}
|
||||
OptionKind::Insecure(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.insecure = value;
|
||||
entry_options.insecure = value;
|
||||
}
|
||||
OptionKind::IpV4(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.ip_resolve = if value {
|
||||
entry_options.ip_resolve = if value {
|
||||
IpResolve::IpV4
|
||||
} else {
|
||||
IpResolve::IpV6
|
||||
@ -163,7 +163,7 @@ pub fn get_entry_options(
|
||||
}
|
||||
OptionKind::IpV6(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.ip_resolve = if value {
|
||||
entry_options.ip_resolve = if value {
|
||||
IpResolve::IpV6
|
||||
} else {
|
||||
IpResolve::IpV4
|
||||
@ -171,56 +171,56 @@ pub fn get_entry_options(
|
||||
}
|
||||
OptionKind::MaxRedirect(value) => {
|
||||
let value = eval_natural_option(value, variables)?;
|
||||
runner_options.max_redirect = Some(value as usize);
|
||||
entry_options.max_redirect = Some(value as usize);
|
||||
}
|
||||
OptionKind::NetRc(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.netrc = value;
|
||||
entry_options.netrc = value;
|
||||
}
|
||||
OptionKind::NetRcFile(value) => {
|
||||
let filename = eval_template(value, variables)?;
|
||||
runner_options.netrc_file = Some(filename);
|
||||
entry_options.netrc_file = Some(filename);
|
||||
}
|
||||
OptionKind::NetRcOptional(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.netrc_optional = value;
|
||||
entry_options.netrc_optional = value;
|
||||
}
|
||||
OptionKind::Output(output) => {
|
||||
let filename = eval_template(output, variables)?;
|
||||
let output = Output::new(&filename);
|
||||
runner_options.output = Some(output);
|
||||
entry_options.output = Some(output);
|
||||
}
|
||||
OptionKind::PathAsIs(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.path_as_is = value;
|
||||
entry_options.path_as_is = value;
|
||||
}
|
||||
OptionKind::Proxy(value) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
runner_options.proxy = Some(value);
|
||||
entry_options.proxy = Some(value);
|
||||
}
|
||||
OptionKind::Resolve(value) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
runner_options.resolves.push(value);
|
||||
entry_options.resolves.push(value);
|
||||
}
|
||||
OptionKind::Retry(value) => {
|
||||
let value = eval_retry_option(value, variables)?;
|
||||
runner_options.retry = value;
|
||||
entry_options.retry = value;
|
||||
}
|
||||
OptionKind::RetryInterval(value) => {
|
||||
let value = eval_natural_option(value, variables)?;
|
||||
runner_options.retry_interval = Duration::from_millis(value);
|
||||
entry_options.retry_interval = Duration::from_millis(value);
|
||||
}
|
||||
OptionKind::Skip(value) => {
|
||||
let value = eval_boolean_option(value, variables)?;
|
||||
runner_options.skip = value;
|
||||
entry_options.skip = value;
|
||||
}
|
||||
OptionKind::UnixSocket(value) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
runner_options.unix_socket = Some(value);
|
||||
entry_options.unix_socket = Some(value);
|
||||
}
|
||||
OptionKind::User(value) => {
|
||||
let value = eval_template(value, variables)?;
|
||||
runner_options.user = Some(value);
|
||||
entry_options.user = Some(value);
|
||||
}
|
||||
OptionKind::Variable(VariableDefinition { name, value, .. }) => {
|
||||
let value = eval_variable_value(value, variables)?;
|
||||
@ -240,7 +240,7 @@ pub fn get_entry_options(
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(runner_options)
|
||||
Ok(entry_options)
|
||||
}
|
||||
|
||||
/// Logs an entry option.
|
||||
|
@ -73,7 +73,7 @@ pub fn eval_html(html: &str, expr: &str) -> Result<Value, XpathError> {
|
||||
/// - <https://github.com/Orange-OpenSource/hurl/issues/1535>
|
||||
/// These two functions should be removed when the issue is fixed in libxml crate.
|
||||
fn try_usize_to_i32(value: usize) -> Result<i32, XmlParseError> {
|
||||
if cfg!(target_pointer_width = "16") || (value < i32::max_value() as usize) {
|
||||
if cfg!(target_pointer_width = "16") || (value < i32::MAX as usize) {
|
||||
// Cannot safely use our value comparison, but the conversion if always safe.
|
||||
// Or, if the value can be safely represented as a 32-bit signed integer.
|
||||
Ok(value as i32)
|
||||
|
@ -59,10 +59,7 @@ pub fn url(arg_matches: &ArgMatches) -> String {
|
||||
}
|
||||
|
||||
pub fn headers(arg_matches: &ArgMatches) -> Vec<String> {
|
||||
let mut headers = match get_strings(arg_matches, "headers") {
|
||||
None => vec![],
|
||||
Some(v) => v,
|
||||
};
|
||||
let mut headers = get_strings(arg_matches, "headers").unwrap_or_default();
|
||||
if !has_content_type(&headers) {
|
||||
if let Some(data) = get_string(arg_matches, "data") {
|
||||
if !data.starts_with('@') {
|
||||
|
Loading…
Reference in New Issue
Block a user