allow insecure server connections when using SSL (#4219)

Fixes #4211

Signed-off-by: nibon7 <nibon7@163.com>
This commit is contained in:
nibon7 2021-12-23 03:48:43 +08:00 committed by GitHub
parent d32aec5906
commit 6cd124ddb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 13 deletions

View File

@ -36,6 +36,7 @@ impl WholeStreamCommand for Command {
Some('p'), Some('p'),
) )
.switch("raw", "fetch contents as text rather than a table", Some('r')) .switch("raw", "fetch contents as text rather than a table", Some('r'))
.switch("insecure", "allow insecure server connections when using SSL", Some('k'))
.filter() .filter()
} }
@ -78,6 +79,7 @@ fn run_fetch(args: CommandArgs) -> Result<ActionStream, ShellError> {
) )
})?, })?,
fetch_helper.has_raw, fetch_helper.has_raw,
fetch_helper.has_insecure,
fetch_helper.user.clone(), fetch_helper.user.clone(),
fetch_helper.password, fetch_helper.password,
))] ))]
@ -92,6 +94,7 @@ pub struct Fetch {
pub path: Option<Value>, pub path: Option<Value>,
pub tag: Tag, pub tag: Tag,
pub has_raw: bool, pub has_raw: bool,
pub has_insecure: bool,
pub user: Option<String>, pub user: Option<String>,
pub password: Option<String>, pub password: Option<String>,
} }
@ -102,6 +105,7 @@ impl Fetch {
path: None, path: None,
tag: Tag::unknown(), tag: Tag::unknown(),
has_raw: false, has_raw: false,
has_insecure: false,
user: None, user: None,
password: None, password: None,
} }
@ -121,6 +125,8 @@ impl Fetch {
self.has_raw = args.has_flag("raw"); self.has_raw = args.has_flag("raw");
self.has_insecure = args.has_flag("insecure");
self.user = args.get_flag("user")?; self.user = args.get_flag("user")?;
self.password = args.get_flag("password")?; self.password = args.get_flag("password")?;
@ -132,13 +138,14 @@ impl Fetch {
pub async fn fetch( pub async fn fetch(
path: &Value, path: &Value,
has_raw: bool, has_raw: bool,
has_insecure: bool,
user: Option<String>, user: Option<String>,
password: Option<String>, password: Option<String>,
) -> ReturnValue { ) -> ReturnValue {
let path_str = path.as_string()?; let path_str = path.as_string()?;
let path_span = path.tag.span; let path_span = path.tag.span;
let result = helper(&path_str, path_span, has_raw, user, password).await; let result = helper(&path_str, path_span, has_raw, has_insecure, user, password).await;
if let Err(e) = result { if let Err(e) = result {
return Err(e); return Err(e);
@ -168,6 +175,7 @@ async fn helper(
location: &str, location: &str,
span: Span, span: Span,
has_raw: bool, has_raw: bool,
has_insecure: bool,
user: Option<String>, user: Option<String>,
password: Option<String>, password: Option<String>,
) -> std::result::Result<(Option<String>, Value), ShellError> { ) -> std::result::Result<(Option<String>, Value), ShellError> {
@ -188,7 +196,7 @@ async fn helper(
_ => None, _ => None,
}; };
let client = http_client(); let client = http_client(has_insecure);
let mut request = client.get(url); let mut request = client.get(url);
if let Some(login) = login { if let Some(login) = login {
@ -360,10 +368,10 @@ async fn helper(
// Only panics if the user agent is invalid but we define it statically so either // Only panics if the user agent is invalid but we define it statically so either
// it always or never fails // it always or never fails
#[allow(clippy::unwrap_used)] fn http_client(allow_insecure: bool) -> reqwest::Client {
fn http_client() -> reqwest::Client {
reqwest::Client::builder() reqwest::Client::builder()
.user_agent("nushell") .user_agent("nushell")
.danger_accept_invalid_certs(allow_insecure)
.build() .build()
.unwrap() .expect("Failed to build reqwest client")
} }

View File

@ -53,6 +53,11 @@ impl WholeStreamCommand for Command {
"return values as a string instead of a table", "return values as a string instead of a table",
Some('r'), Some('r'),
) )
.switch(
"insecure",
"allow insecure server connections when using SSL",
Some('k'),
)
.filter() .filter()
} }
@ -91,6 +96,7 @@ fn run_post(args: CommandArgs) -> Result<ActionStream, ShellError> {
ShellError::labeled_error("expected a 'path'", "expected a 'path'", &helper.tag) ShellError::labeled_error("expected a 'path'", "expected a 'path'", &helper.tag)
})?, })?,
helper.has_raw, helper.has_raw,
helper.has_insecure,
&helper.body.clone().ok_or_else(|| { &helper.body.clone().ok_or_else(|| {
ShellError::labeled_error("expected a 'body'", "expected a 'body'", &helper.tag) ShellError::labeled_error("expected a 'body'", "expected a 'body'", &helper.tag)
})?, })?,
@ -114,6 +120,7 @@ pub enum HeaderKind {
pub struct Post { pub struct Post {
pub path: Option<Value>, pub path: Option<Value>,
pub has_raw: bool, pub has_raw: bool,
pub has_insecure: bool,
pub body: Option<Value>, pub body: Option<Value>,
pub user: Option<String>, pub user: Option<String>,
pub password: Option<String>, pub password: Option<String>,
@ -126,6 +133,7 @@ impl Post {
Post { Post {
path: None, path: None,
has_raw: false, has_raw: false,
has_insecure: false,
body: None, body: None,
user: None, user: None,
password: None, password: None,
@ -156,6 +164,8 @@ impl Post {
self.has_raw = args.has_flag("raw"); self.has_raw = args.has_flag("raw");
self.has_insecure = args.has_flag("insecure");
self.user = args.get_flag("user")?; self.user = args.get_flag("user")?;
self.password = args.get_flag("password")?; self.password = args.get_flag("password")?;
@ -169,6 +179,7 @@ impl Post {
pub async fn post_helper( pub async fn post_helper(
path: &Value, path: &Value,
has_raw: bool, has_raw: bool,
has_insecure: bool,
body: &Value, body: &Value,
user: Option<String>, user: Option<String>,
password: Option<String>, password: Option<String>,
@ -177,8 +188,16 @@ pub async fn post_helper(
let path_tag = path.tag.clone(); let path_tag = path.tag.clone();
let path_str = path.as_string()?; let path_str = path.as_string()?;
let (file_extension, contents, contents_tag) = let (file_extension, contents, contents_tag) = post(
post(&path_str, body, user, password, headers, path_tag.clone()).await?; &path_str,
has_insecure,
body,
user,
password,
headers,
path_tag.clone(),
)
.await?;
let file_extension = if has_raw { let file_extension = if has_raw {
None None
@ -202,6 +221,7 @@ pub async fn post_helper(
pub async fn post( pub async fn post(
location: &str, location: &str,
allow_insecure: bool,
body: &Value, body: &Value,
user: Option<String>, user: Option<String>,
password: Option<String>, password: Option<String>,
@ -219,7 +239,9 @@ pub async fn post(
value: UntaggedValue::Primitive(Primitive::String(body_str)), value: UntaggedValue::Primitive(Primitive::String(body_str)),
.. ..
} => { } => {
let mut s = http_client().post(location).body(body_str.to_string()); let mut s = http_client(allow_insecure)
.post(location)
.body(body_str.to_string());
if let Some(login) = login { if let Some(login) = login {
s = s.header("Authorization", format!("Basic {}", login)); s = s.header("Authorization", format!("Basic {}", login));
} }
@ -237,7 +259,9 @@ pub async fn post(
value: UntaggedValue::Primitive(Primitive::Binary(b)), value: UntaggedValue::Primitive(Primitive::Binary(b)),
.. ..
} => { } => {
let mut s = http_client().post(location).body(Vec::from(&b[..])); let mut s = http_client(allow_insecure)
.post(location)
.body(Vec::from(&b[..]));
if let Some(login) = login { if let Some(login) = login {
s = s.header("Authorization", format!("Basic {}", login)); s = s.header("Authorization", format!("Basic {}", login));
} }
@ -247,7 +271,9 @@ pub async fn post(
match value_to_json_value(&value.clone().into_untagged_value()) { match value_to_json_value(&value.clone().into_untagged_value()) {
Ok(json_value) => match serde_json::to_string(&json_value) { Ok(json_value) => match serde_json::to_string(&json_value) {
Ok(result_string) => { Ok(result_string) => {
let mut s = http_client().post(location).body(result_string); let mut s = http_client(allow_insecure)
.post(location)
.body(result_string);
if let Some(login) = login { if let Some(login) = login {
s = s.header("Authorization", format!("Basic {}", login)); s = s.header("Authorization", format!("Basic {}", login));
@ -611,10 +637,10 @@ fn extract_header_value(args: &CommandArgs, key: &str) -> Result<Option<String>,
// Only panics if the user agent is invalid but we define it statically so either // Only panics if the user agent is invalid but we define it statically so either
// it always or never fails // it always or never fails
#[allow(clippy::unwrap_used)] fn http_client(allow_insecure: bool) -> reqwest::Client {
fn http_client() -> reqwest::Client {
reqwest::Client::builder() reqwest::Client::builder()
.user_agent("nushell") .user_agent("nushell")
.danger_accept_invalid_certs(allow_insecure)
.build() .build()
.unwrap() .expect("Failed to build reqwest client")
} }