mirror of
https://github.com/nushell/nushell
synced 2024-12-28 22:13:10 +00:00
Implement login for the fetch command (#1915)
This commit is contained in:
parent
48ee20782f
commit
3a6a3d7409
4 changed files with 50 additions and 5 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2446,6 +2446,7 @@ dependencies = [
|
||||||
name = "nu_plugin_fetch"
|
name = "nu_plugin_fetch"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.12.1",
|
||||||
"futures 0.3.5",
|
"futures 0.3.5",
|
||||||
"nu-build",
|
"nu-build",
|
||||||
"nu-errors",
|
"nu-errors",
|
||||||
|
|
|
@ -17,6 +17,7 @@ nu-errors = { path = "../nu-errors", version = "0.14.1" }
|
||||||
futures = { version = "0.3", features = ["compat", "io-compat"] }
|
futures = { version = "0.3", features = ["compat", "io-compat"] }
|
||||||
surf = "1.0.3"
|
surf = "1.0.3"
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
|
base64 = "0.12.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
nu-build = { version = "0.14.1", path = "../nu-build" }
|
nu-build = { version = "0.14.1", path = "../nu-build" }
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use base64::encode;
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{CallInfo, CommandAction, ReturnSuccess, ReturnValue, UntaggedValue, Value};
|
use nu_protocol::{CallInfo, CommandAction, ReturnSuccess, ReturnValue, UntaggedValue, Value};
|
||||||
|
@ -11,6 +12,8 @@ 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 user: Option<String>,
|
||||||
|
pub password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fetch {
|
impl Fetch {
|
||||||
|
@ -19,6 +22,8 @@ impl Fetch {
|
||||||
path: None,
|
path: None,
|
||||||
tag: Tag::unknown(),
|
tag: Tag::unknown(),
|
||||||
has_raw: false,
|
has_raw: false,
|
||||||
|
user: None,
|
||||||
|
password: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +42,30 @@ impl Fetch {
|
||||||
|
|
||||||
self.has_raw = call_info.args.has("raw");
|
self.has_raw = call_info.args.has("raw");
|
||||||
|
|
||||||
|
self.user = match call_info.args.get("user") {
|
||||||
|
Some(user) => Some(user.as_string()?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.password = match call_info.args.get("password") {
|
||||||
|
Some(password) => Some(password.as_string()?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value())
|
ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_helper(path: &Value, has_raw: bool) -> ReturnValue {
|
pub async fn fetch_helper(
|
||||||
|
path: &Value,
|
||||||
|
has_raw: bool,
|
||||||
|
user: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
|
) -> 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 = fetch(&path_str, path_span, has_raw).await;
|
let result = fetch(&path_str, path_span, has_raw, user, password).await;
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
|
@ -76,6 +96,8 @@ pub async fn fetch(
|
||||||
location: &str,
|
location: &str,
|
||||||
span: Span,
|
span: Span,
|
||||||
has_raw: bool,
|
has_raw: bool,
|
||||||
|
user: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
) -> Result<(Option<String>, UntaggedValue, Tag), ShellError> {
|
) -> Result<(Option<String>, UntaggedValue, Tag), ShellError> {
|
||||||
if url::Url::parse(location).is_err() {
|
if url::Url::parse(location).is_err() {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
|
@ -84,9 +106,16 @@ pub async fn fetch(
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
let login = match (user, password) {
|
||||||
let response = surf::get(location).await;
|
(Some(user), Some(password)) => Some(encode(&format!("{}:{}", user, password))),
|
||||||
match response {
|
(Some(user), _) => Some(encode(&format!("{}:", user))),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let mut response = surf::get(location);
|
||||||
|
if let Some(login) = login {
|
||||||
|
response = response.set_header("Authorization", format!("Basic {}", login));
|
||||||
|
}
|
||||||
|
match response.await {
|
||||||
Ok(mut r) => match r.headers().get("content-type") {
|
Ok(mut r) => match r.headers().get("content-type") {
|
||||||
Some(content_type) => {
|
Some(content_type) => {
|
||||||
let content_type = Mime::from_str(content_type).map_err(|_| {
|
let content_type = Mime::from_str(content_type).map_err(|_| {
|
||||||
|
|
|
@ -15,6 +15,18 @@ impl Plugin for Fetch {
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
"the URL to fetch the contents from",
|
"the URL to fetch the contents from",
|
||||||
)
|
)
|
||||||
|
.named(
|
||||||
|
"user",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"the username when authenticating",
|
||||||
|
Some('u'),
|
||||||
|
)
|
||||||
|
.named(
|
||||||
|
"password",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"the password when authenticating",
|
||||||
|
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'))
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
@ -26,6 +38,8 @@ impl Plugin for Fetch {
|
||||||
ShellError::labeled_error("internal error: path not set", "path not set", &self.tag)
|
ShellError::labeled_error("internal error: path not set", "path not set", &self.tag)
|
||||||
})?,
|
})?,
|
||||||
self.has_raw,
|
self.has_raw,
|
||||||
|
self.user.clone(),
|
||||||
|
self.password.clone(),
|
||||||
))])
|
))])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue