"Use pipeline data in http post command. Added metadata with content_type"
This commit is contained in:
parent
0d79b63711
commit
c9eb9f20c3
|
@ -90,6 +90,9 @@ impl Command for Metadata {
|
|||
"source",
|
||||
Value::string(path.to_string_lossy().to_string(), head),
|
||||
),
|
||||
PipelineMetadata {
|
||||
data_source: DataSource::ContentType(content_type),
|
||||
} => record.push("content_type", Value::string(content_type, head)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +146,9 @@ fn build_metadata_record(arg: &Value, metadata: Option<&PipelineMetadata>, head:
|
|||
"source",
|
||||
Value::string(path.to_string_lossy().to_string(), head),
|
||||
),
|
||||
PipelineMetadata {
|
||||
data_source: DataSource::ContentType(content_type),
|
||||
} => record.push("content_type", Value::string(content_type, head)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::ast::PathMember;
|
||||
use nu_protocol::{ast::PathMember, PipelineMetadata};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ToJson;
|
||||
|
@ -61,7 +61,11 @@ impl Command for ToJson {
|
|||
|
||||
match json_result {
|
||||
Ok(serde_json_string) => {
|
||||
Ok(Value::string(serde_json_string, span).into_pipeline_data())
|
||||
let res = Value::string(serde_json_string, span);
|
||||
let metadata = PipelineMetadata {
|
||||
data_source: nu_protocol::DataSource::ContentType("application/json".to_string())
|
||||
};
|
||||
Ok(PipelineData::Value(res, Some(metadata)))
|
||||
}
|
||||
_ => Ok(Value::error(
|
||||
ShellError::CantConvert {
|
||||
|
|
|
@ -180,88 +180,135 @@ impl From<ShellError> for ShellErrorOrRequestError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HttpBody {
|
||||
Value(Value),
|
||||
ByteStream(ByteStream),
|
||||
None,
|
||||
}
|
||||
|
||||
pub fn send_request(
|
||||
request: Request,
|
||||
body: Option<Value>,
|
||||
content_type: Option<String>,
|
||||
ctrl_c: Option<Arc<AtomicBool>>,
|
||||
) -> Result<Response, ShellErrorOrRequestError> {
|
||||
let request_url = request.url().to_string();
|
||||
if body.is_none() {
|
||||
return send_cancellable_request(&request_url, Box::new(|| request.call()), ctrl_c);
|
||||
}
|
||||
let body = body.expect("Should never be none.");
|
||||
|
||||
let body_type = match content_type {
|
||||
Some(it) if it == "application/json" => BodyType::Json,
|
||||
Some(it) if it == "application/x-www-form-urlencoded" => BodyType::Form,
|
||||
_ => BodyType::Unknown,
|
||||
let body = if let Some(body) = body {
|
||||
HttpBody::Value(body)
|
||||
} else {
|
||||
HttpBody::None
|
||||
};
|
||||
match body {
|
||||
Value::Binary { val, .. } => send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(move || request.send_bytes(&val)),
|
||||
ctrl_c,
|
||||
),
|
||||
Value::String { .. } if body_type == BodyType::Json => {
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(&request_url, Box::new(|| request.send_json(data)), ctrl_c)
|
||||
}
|
||||
Value::String { val, .. } => send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(move || request.send_string(&val)),
|
||||
ctrl_c,
|
||||
),
|
||||
Value::Record { .. } if body_type == BodyType::Json => {
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(&request_url, Box::new(|| request.send_json(data)), ctrl_c)
|
||||
}
|
||||
Value::Record { val, .. } if body_type == BodyType::Form => {
|
||||
let mut data: Vec<(String, String)> = Vec::with_capacity(val.len());
|
||||
|
||||
for (col, val) in val.into_owned() {
|
||||
data.push((col, val.coerce_into_string()?))
|
||||
}
|
||||
send_request2(request, body, content_type, ctrl_c)
|
||||
}
|
||||
|
||||
let request_fn = move || {
|
||||
// coerce `data` into a shape that send_form() is happy with
|
||||
let data = data
|
||||
.iter()
|
||||
.map(|(a, b)| (a.as_str(), b.as_str()))
|
||||
.collect::<Vec<(&str, &str)>>();
|
||||
request.send_form(&data)
|
||||
// remove once all commands have been migrated
|
||||
pub fn send_request2(
|
||||
request: Request,
|
||||
http_body: HttpBody,
|
||||
content_type: Option<String>,
|
||||
ctrl_c: Option<Arc<AtomicBool>>,
|
||||
) -> Result<Response, ShellErrorOrRequestError> {
|
||||
let request_url = request.url().to_string();
|
||||
|
||||
match http_body {
|
||||
HttpBody::None => {
|
||||
return send_cancellable_request(&request_url, Box::new(|| request.call()), ctrl_c);
|
||||
}
|
||||
HttpBody::ByteStream(byte_stream) => {
|
||||
let bytes = byte_stream.into_bytes()?;
|
||||
|
||||
send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(move || request.send_bytes(&bytes)),
|
||||
ctrl_c,
|
||||
)
|
||||
}
|
||||
HttpBody::Value(body) => {
|
||||
let body_type = match content_type {
|
||||
Some(it) if it == "application/json" => BodyType::Json,
|
||||
Some(it) if it == "application/x-www-form-urlencoded" => BodyType::Form,
|
||||
_ => BodyType::Unknown,
|
||||
};
|
||||
send_cancellable_request(&request_url, Box::new(request_fn), ctrl_c)
|
||||
}
|
||||
Value::List { vals, .. } if body_type == BodyType::Form => {
|
||||
if vals.len() % 2 != 0 {
|
||||
return Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
|
||||
match body {
|
||||
Value::Binary { val, .. } => send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(move || request.send_bytes(&val)),
|
||||
ctrl_c,
|
||||
),
|
||||
Value::String { .. } if body_type == BodyType::Json => {
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(|| request.send_json(data)),
|
||||
ctrl_c,
|
||||
)
|
||||
}
|
||||
Value::String { val, .. } => send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(move || request.send_string(&val)),
|
||||
ctrl_c,
|
||||
),
|
||||
Value::Record { .. } if body_type == BodyType::Json => {
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(|| request.send_json(data)),
|
||||
ctrl_c,
|
||||
)
|
||||
}
|
||||
Value::Record { val, .. } if body_type == BodyType::Form => {
|
||||
let mut data: Vec<(String, String)> = Vec::with_capacity(val.len());
|
||||
|
||||
for (col, val) in val.into_owned() {
|
||||
data.push((col, val.coerce_into_string()?))
|
||||
}
|
||||
|
||||
let request_fn = move || {
|
||||
// coerce `data` into a shape that send_form() is happy with
|
||||
let data = data
|
||||
.iter()
|
||||
.map(|(a, b)| (a.as_str(), b.as_str()))
|
||||
.collect::<Vec<(&str, &str)>>();
|
||||
request.send_form(&data)
|
||||
};
|
||||
send_cancellable_request(&request_url, Box::new(request_fn), ctrl_c)
|
||||
}
|
||||
Value::List { vals, .. } if body_type == BodyType::Form => {
|
||||
if vals.len() % 2 != 0 {
|
||||
return Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
|
||||
msg: "unsupported body input".into(),
|
||||
}));
|
||||
}
|
||||
|
||||
let data = vals
|
||||
.chunks(2)
|
||||
.map(|it| Ok((it[0].coerce_string()?, it[1].coerce_string()?)))
|
||||
.collect::<Result<Vec<(String, String)>, ShellErrorOrRequestError>>()?;
|
||||
|
||||
let request_fn = move || {
|
||||
// coerce `data` into a shape that send_form() is happy with
|
||||
let data = data
|
||||
.iter()
|
||||
.map(|(a, b)| (a.as_str(), b.as_str()))
|
||||
.collect::<Vec<(&str, &str)>>();
|
||||
request.send_form(&data)
|
||||
};
|
||||
send_cancellable_request(&request_url, Box::new(request_fn), ctrl_c)
|
||||
}
|
||||
Value::List { .. } if body_type == BodyType::Json => {
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(
|
||||
&request_url,
|
||||
Box::new(|| request.send_json(data)),
|
||||
ctrl_c,
|
||||
)
|
||||
}
|
||||
_ => Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
|
||||
msg: "unsupported body input".into(),
|
||||
}));
|
||||
})),
|
||||
}
|
||||
|
||||
let data = vals
|
||||
.chunks(2)
|
||||
.map(|it| Ok((it[0].coerce_string()?, it[1].coerce_string()?)))
|
||||
.collect::<Result<Vec<(String, String)>, ShellErrorOrRequestError>>()?;
|
||||
|
||||
let request_fn = move || {
|
||||
// coerce `data` into a shape that send_form() is happy with
|
||||
let data = data
|
||||
.iter()
|
||||
.map(|(a, b)| (a.as_str(), b.as_str()))
|
||||
.collect::<Vec<(&str, &str)>>();
|
||||
request.send_form(&data)
|
||||
};
|
||||
send_cancellable_request(&request_url, Box::new(request_fn), ctrl_c)
|
||||
}
|
||||
Value::List { .. } if body_type == BodyType::Json => {
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(&request_url, Box::new(|| request.send_json(data)), ctrl_c)
|
||||
}
|
||||
_ => Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
|
||||
msg: "unsupported body input".into(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use crate::network::http::client::{
|
||||
check_response_redirection, http_client, http_parse_redirect_mode, http_parse_url,
|
||||
request_add_authorization_header, request_add_custom_headers, request_handle_response,
|
||||
request_set_timeout, send_request, RequestFlags,
|
||||
request_set_timeout, RequestFlags, HttpBody
|
||||
};
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::DataSource;
|
||||
|
||||
use super::client::send_request2;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SubCommand;
|
||||
|
@ -15,10 +18,10 @@ impl Command for SubCommand {
|
|||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("http post")
|
||||
.input_output_types(vec![(Type::Nothing, Type::Any)])
|
||||
.input_output_types(vec![(Type::Any, Type::Any)])
|
||||
.allow_variants_without_examples(true)
|
||||
.required("URL", SyntaxShape::String, "The URL to post to.")
|
||||
.required("data", SyntaxShape::Any, "The contents of the post body.")
|
||||
.optional("data", SyntaxShape::Any, "The contents of the post body. Required unless part of pipeline.")
|
||||
.named(
|
||||
"user",
|
||||
SyntaxShape::Any,
|
||||
|
@ -129,7 +132,7 @@ impl Command for SubCommand {
|
|||
struct Arguments {
|
||||
url: Value,
|
||||
headers: Option<Value>,
|
||||
data: Value,
|
||||
data: HttpBody,
|
||||
content_type: Option<String>,
|
||||
raw: bool,
|
||||
insecure: bool,
|
||||
|
@ -145,13 +148,34 @@ fn run_post(
|
|||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
|
||||
let (data, maybe_metadata) = call.opt::<Value>(engine_state, stack, 1)?
|
||||
.map(|v| (HttpBody::Value(v), None))
|
||||
.unwrap_or_else(|| match input {
|
||||
PipelineData::Value(v, metadata) => (HttpBody::Value(v), metadata),
|
||||
PipelineData::ByteStream(byte_stream, metadata) => (HttpBody::ByteStream(byte_stream), metadata),
|
||||
_ => (HttpBody::None, None)
|
||||
});
|
||||
let content_type = call.get_flag(engine_state, stack, "content-type")?
|
||||
.or_else(|| {
|
||||
if let Some(metadata) = maybe_metadata {
|
||||
match metadata.data_source {
|
||||
DataSource::ContentType(content_type) => Some(content_type),
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let args = Arguments {
|
||||
url: call.req(engine_state, stack, 0)?,
|
||||
headers: call.get_flag(engine_state, stack, "headers")?,
|
||||
data: call.req(engine_state, stack, 1)?,
|
||||
content_type: call.get_flag(engine_state, stack, "content-type")?,
|
||||
data,
|
||||
content_type,
|
||||
raw: call.has_flag(engine_state, stack, "raw")?,
|
||||
insecure: call.has_flag(engine_state, stack, "insecure")?,
|
||||
user: call.get_flag(engine_state, stack, "user")?,
|
||||
|
@ -185,7 +209,7 @@ fn helper(
|
|||
request = request_add_authorization_header(args.user, args.password, request);
|
||||
request = request_add_custom_headers(args.headers, request)?;
|
||||
|
||||
let response = send_request(request.clone(), Some(args.data), args.content_type, ctrl_c);
|
||||
let response = send_request2(request.clone(), args.data, args.content_type, ctrl_c);
|
||||
|
||||
let request_flags = RequestFlags {
|
||||
raw: args.raw,
|
||||
|
|
|
@ -15,4 +15,5 @@ pub enum DataSource {
|
|||
Ls,
|
||||
HtmlThemes,
|
||||
FilePath(PathBuf),
|
||||
ContentType(String)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user