Add serialization for JSON and form bodies in post (#4764)

* Add serialization for JSON and form bodies in `post`

* Reuse code from `to json` instead of duplicating

* Fix formatting. Oops
This commit is contained in:
Genna Wingert 2022-03-07 17:49:45 +01:00 committed by GitHub
parent a2723c2ba4
commit 0a95bc7e60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 3 deletions

View File

@ -57,7 +57,7 @@ quick-xml = "0.22"
rand = "0.8"
rayon = "1.5.1"
regex = "1.5.4"
reqwest = {version = "0.11", features = ["blocking"] }
reqwest = {version = "0.11", features = ["blocking", "json"] }
roxmltree = "0.14.0"
rust-embed = "6.3.0"
serde = { version="1.0.123", features=["derive"] }

View File

@ -22,3 +22,5 @@ pub use nuon::ToNuon;
pub use tsv::ToTsv;
pub use xml::ToXml;
pub use yaml::ToYaml;
pub(crate) use json::value_to_json_value;

View File

@ -1,3 +1,4 @@
use crate::formats::value_to_json_value;
use base64::encode;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
@ -98,6 +99,11 @@ impl Command for SubCommand {
example: "post -H [my-header-key my-header-value] url.com",
result: None,
},
Example {
description: "Post content to url.com with a json body",
example: "post -t application/json url.com { field: value }",
result: None,
},
]
}
}
@ -113,6 +119,14 @@ struct Arguments {
content_type: Option<String>,
content_length: Option<String>,
}
#[derive(PartialEq, Eq)]
enum BodyType {
Json,
Form,
Unknown,
}
fn run_post(
engine_state: &EngineState,
stack: &mut Stack,
@ -127,8 +141,8 @@ fn run_post(
user: call.get_flag(engine_state, stack, "user")?,
password: call.get_flag(engine_state, stack, "password")?,
insecure: call.get_flag(engine_state, stack, "insecure")?,
content_type: call.get_flag(engine_state, stack, "content_type")?,
content_length: call.get_flag(engine_state, stack, "content_length")?,
content_type: call.get_flag(engine_state, stack, "content-type")?,
content_length: call.get_flag(engine_state, stack, "content-length")?,
};
helper(engine_state, stack, call, args)
}
@ -178,6 +192,13 @@ fn helper(
(Some(user), _) => Some(encode(&format!("{}:", user))),
_ => None,
};
let body_type = match &args.content_type {
Some(it) if it == "application/json" => BodyType::Json,
Some(it) if it == "application/x-www-form-urlencoded" => BodyType::Form,
_ => BodyType::Unknown,
};
let mut request = http_client(args.insecure.is_some()).post(location);
match body {
Value::Binary { val, .. } => {
@ -186,6 +207,24 @@ fn helper(
Value::String { val, .. } => {
request = request.body(val);
}
Value::Record { .. } if body_type == BodyType::Json => {
let data = value_to_json_value(&body)?;
request = request.json(&data);
}
Value::Record { .. } if body_type == BodyType::Form => {
let data = value_to_json_value(&body)?;
request = request.form(&data);
}
Value::List { vals, .. } if body_type == BodyType::Form => {
if vals.len() % 2 != 0 {
return Err(ShellError::IOError("unsupported body input".into()));
}
let data = vals
.chunks(2)
.map(|it| Ok((it[0].as_string()?, it[1].as_string()?)))
.collect::<Result<Vec<(String, String)>, ShellError>>()?;
request = request.form(&data)
}
_ => {
return Err(ShellError::IOError("unsupported body input".into()));
}