Skip to content

Commit

Permalink
Use Template for filename type
Browse files Browse the repository at this point in the history
  • Loading branch information
fabricereix committed Jan 6, 2024
1 parent 4511e37 commit 6ac325d
Show file tree
Hide file tree
Showing 17 changed files with 345 additions and 147 deletions.
4 changes: 4 additions & 0 deletions integration/hurl/tests_ok/post_file.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ POST http://localhost:8000/post-file
file,data.bin;
HTTP 200

POST http://localhost:8000/post-file
file,{{filename}};
HTTP 200

POST http://localhost:8000/post-file
file,post_file_with\ space;
HTTP 200
2 changes: 1 addition & 1 deletion integration/hurl/tests_ok/post_file.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Set-StrictMode -Version latest
$ErrorActionPreference = 'Stop'
hurl tests_ok/post_file.hurl --verbose
hurl tests_ok/post_file.hurl --variable filename=data.bin --verbose
2 changes: 1 addition & 1 deletion integration/hurl/tests_ok/post_file.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash
set -Eeuo pipefail
hurl tests_ok/post_file.hurl --verbose
hurl tests_ok/post_file.hurl --variable filename=data.bin --verbose
2 changes: 1 addition & 1 deletion packages/hurl/src/cli/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn log_request(request: Request) {
};
eprintln!(
"\r{}: {}{}",
file_param.key, file_param.value.filename.value, content_type
file_param.key, file_param.value.filename, content_type
);
}
}
Expand Down
29 changes: 21 additions & 8 deletions packages/hurl/src/runner/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,21 @@ pub fn eval_bytes(
Bytes::Base64(Base64 { value, .. }) => Ok(http::Body::Binary(value.clone())),
Bytes::Hex(Hex { value, .. }) => Ok(http::Body::Binary(value.clone())),
Bytes::File(File { filename, .. }) => {
let value = eval_file(filename, context_dir)?;
Ok(http::Body::File(value, filename.value.clone()))
let value = eval_file(filename, variables, context_dir)?;
let filename = eval_template(filename, variables)?;
Ok(http::Body::File(value, filename))
}
}
}

pub fn eval_file(filename: &Filename, context_dir: &ContextDir) -> Result<Vec<u8>, Error> {
pub fn eval_file(
filename: &Template,
variables: &HashMap<String, Value>,
context_dir: &ContextDir,
) -> Result<Vec<u8>, Error> {
let file = eval_template(filename, variables)?;
// In order not to leak any private date, we check that the user provided file
// is a child of the context directory.
let file = filename.value.clone();
if !context_dir.is_access_allowed(&file) {
let inner = RunnerError::UnauthorizedFileAccess {
path: PathBuf::from(file),
Expand Down Expand Up @@ -100,9 +105,13 @@ mod tests {

let bytes = Bytes::File(File {
space0: whitespace.clone(),
filename: Filename {
value: String::from("tests/data.bin"),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(1, 7), Pos::new(1, 15)),
elements: vec![TemplateElement::String {
value: "tests/data.bin".to_string(),
encoded: "tests/data.bin".to_string(),
}],
},
space1: whitespace,
});
Expand All @@ -127,9 +136,13 @@ mod tests {

let bytes = Bytes::File(File {
space0: whitespace.clone(),
filename: Filename {
value: String::from("data.bin"),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(1, 7), Pos::new(1, 15)),
elements: vec![TemplateElement::String {
value: "data.bin".to_string(),
encoded: "data.bin".to_string(),
}],
},
space1: whitespace,
});
Expand Down
166 changes: 105 additions & 61 deletions packages/hurl/src/runner/multipart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,37 +52,44 @@ pub fn eval_file_param(
variables: &HashMap<String, Value>,
) -> Result<http::FileParam, Error> {
let name = eval_template(&file_param.key, variables)?;
let filename = file_param.value.filename.clone();
let data = eval_file(&filename, context_dir)?;
let content_type = file_value_content_type(&file_param.value);
let filename = eval_template(&file_param.value.filename, variables)?;
let data = eval_file(&file_param.value.filename, variables, context_dir)?;
let content_type = file_value_content_type(&file_param.value, variables)?;
Ok(http::FileParam {
name,
filename: filename.value,
filename,
data,
content_type,
})
}

pub fn file_value_content_type(file_value: &FileValue) -> String {
match file_value.content_type.clone() {
None => match Path::new(file_value.filename.value.as_str())
.extension()
.and_then(OsStr::to_str)
{
Some("gif") => "image/gif".to_string(),
Some("jpg") => "image/jpeg".to_string(),
Some("jpeg") => "image/jpeg".to_string(),
Some("png") => "image/png".to_string(),
Some("svg") => "image/svg+xml".to_string(),
Some("txt") => "text/plain".to_string(),
Some("htm") => "text/html".to_string(),
Some("html") => "text/html".to_string(),
Some("pdf") => "application/pdf".to_string(),
Some("xml") => "application/xml".to_string(),
_ => "application/octet-stream".to_string(),
},
pub fn file_value_content_type(
file_value: &FileValue,
variables: &HashMap<String, Value>,
) -> Result<String, Error> {
let value = match file_value.content_type.clone() {
None => {
let value = eval_template(&file_value.filename, variables)?;
match Path::new(value.as_str())
.extension()
.and_then(OsStr::to_str)
{
Some("gif") => "image/gif".to_string(),
Some("jpg") => "image/jpeg".to_string(),
Some("jpeg") => "image/jpeg".to_string(),
Some("png") => "image/png".to_string(),
Some("svg") => "image/svg+xml".to_string(),
Some("txt") => "text/plain".to_string(),
Some("htm") => "text/html".to_string(),
Some("html") => "text/html".to_string(),
Some("pdf") => "application/pdf".to_string(),
Some("xml") => "application/xml".to_string(),
_ => "application/octet-stream".to_string(),
}
}
Some(content_type) => content_type,
}
};
Ok(value)
}

#[cfg(test)]
Expand Down Expand Up @@ -125,9 +132,13 @@ mod tests {
space2: whitespace(),
value: FileValue {
space0: whitespace(),
filename: Filename {
value: "hello.txt".to_string(),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
elements: vec![TemplateElement::String {
value: "hello.txt".to_string(),
encoded: "hello.txt".to_string(),
}],
},
space1: whitespace(),
space2: whitespace(),
Expand All @@ -152,59 +163,92 @@ mod tests {

#[test]
pub fn test_file_value_content_type() {
let variables = HashMap::default();
assert_eq!(
file_value_content_type(&FileValue {
space0: whitespace(),
filename: Filename {
value: "hello.txt".to_string(),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
file_value_content_type(
&FileValue {
space0: whitespace(),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
elements: vec![TemplateElement::String {
value: "hello.txt".to_string(),
encoded: "hello.txt".to_string()
}],
},
space1: whitespace(),
space2: whitespace(),
content_type: None,
},
space1: whitespace(),
space2: whitespace(),
content_type: None,
}),
&variables
)
.unwrap(),
"text/plain".to_string()
);

assert_eq!(
file_value_content_type(&FileValue {
space0: whitespace(),
filename: Filename {
value: "hello.html".to_string(),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
file_value_content_type(
&FileValue {
space0: whitespace(),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
elements: vec![TemplateElement::String {
value: "hello.html".to_string(),
encoded: "hello.html".to_string()
}],
},
space1: whitespace(),
space2: whitespace(),
content_type: None,
},
space1: whitespace(),
space2: whitespace(),
content_type: None,
}),
&variables
)
.unwrap(),
"text/html".to_string()
);

assert_eq!(
file_value_content_type(&FileValue {
space0: whitespace(),
filename: Filename {
value: "hello.txt".to_string(),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
file_value_content_type(
&FileValue {
space0: whitespace(),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
elements: vec![TemplateElement::String {
value: "hello.txt".to_string(),
encoded: "hello.txt".to_string()
}],
},
space1: whitespace(),
space2: whitespace(),
content_type: Some("text/html".to_string()),
},
space1: whitespace(),
space2: whitespace(),
content_type: Some("text/html".to_string()),
}),
&variables
)
.unwrap(),
"text/html".to_string()
);

assert_eq!(
file_value_content_type(&FileValue {
space0: whitespace(),
filename: Filename {
value: "hello".to_string(),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
file_value_content_type(
&FileValue {
space0: whitespace(),
filename: Template {
delimiter: None,
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
elements: vec![TemplateElement::String {
value: "hello".to_string(),
encoded: "hello".to_string()
}],
},
space1: whitespace(),
space2: whitespace(),
content_type: None,
},
space1: whitespace(),
space2: whitespace(),
content_type: None,
}),
&variables
)
.unwrap(),
"application/octet-stream".to_string()
);
}
Expand Down
16 changes: 10 additions & 6 deletions packages/hurl/src/runner/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use hurl_core::ast::{

use crate::http::{IpResolve, RequestedHttpVersion};
use crate::runner::template::{eval_expression, eval_template};
use crate::runner::{template, Error, Number, RunnerError, RunnerOptions, Value};
use crate::runner::{Error, Number, RunnerError, RunnerOptions, Value};
use crate::util::logger::{Logger, Verbosity};

/// Returns a new [`RunnerOptions`] based on the `entry` optional Options section
Expand Down Expand Up @@ -54,13 +54,16 @@ pub fn get_entry_options(
runner_options.aws_sigv4 = Some(value)
}
OptionKind::CaCertificate(filename) => {
runner_options.cacert_file = Some(filename.value.clone())
let value = eval_template(filename, variables)?;
runner_options.cacert_file = Some(value)
}
OptionKind::ClientCert(filename) => {
runner_options.client_cert_file = Some(filename.value.clone())
let value = eval_template(filename, variables)?;
runner_options.client_cert_file = Some(value)
}
OptionKind::ClientKey(filename) => {
runner_options.client_key_file = Some(filename.value.clone())
let value = eval_template(filename, variables)?;
runner_options.client_key_file = Some(value)
}
OptionKind::Compressed(value) => {
let value = eval_boolean_option(value, variables)?;
Expand Down Expand Up @@ -157,7 +160,8 @@ pub fn get_entry_options(
runner_options.max_redirect = Some(value as usize)
}
OptionKind::Output(filename) => {
runner_options.output = Some(filename.value.clone())
let value = eval_template(filename, variables)?;
runner_options.output = Some(value)
}
OptionKind::PathAsIs(value) => {
let value = eval_boolean_option(value, variables)?;
Expand Down Expand Up @@ -346,7 +350,7 @@ fn eval_variable_value(
VariableValue::Bool(v) => Ok(Value::Bool(*v)),
VariableValue::Number(v) => Ok(eval_number(v)),
VariableValue::String(template) => {
let s = template::eval_template(template, variables)?;
let s = eval_template(template, variables)?;
Ok(Value::String(s))
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/hurl/src/runner/predicate_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn eval_predicate_value(
PredicateValue::Null => Ok(Value::Null),
PredicateValue::Number(value) => Ok(Value::Number(eval_number(value))),
PredicateValue::File(value) => {
let value = eval_file(&value.filename, context_dir)?;
let value = eval_file(&value.filename, variables, context_dir)?;
Ok(Value::Bytes(value))
}
PredicateValue::Hex(value) => Ok(Value::Bytes(value.value.clone())),
Expand Down
Loading

0 comments on commit 6ac325d

Please sign in to comment.