mirror of
https://github.com/nushell/nushell
synced 2024-12-28 14:03:09 +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"
|
||||
version = "0.14.1"
|
||||
dependencies = [
|
||||
"base64 0.12.1",
|
||||
"futures 0.3.5",
|
||||
"nu-build",
|
||||
"nu-errors",
|
||||
|
|
|
@ -17,6 +17,7 @@ nu-errors = { path = "../nu-errors", version = "0.14.1" }
|
|||
futures = { version = "0.3", features = ["compat", "io-compat"] }
|
||||
surf = "1.0.3"
|
||||
url = "2.1.1"
|
||||
base64 = "0.12.1"
|
||||
|
||||
[build-dependencies]
|
||||
nu-build = { version = "0.14.1", path = "../nu-build" }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use base64::encode;
|
||||
use mime::Mime;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CallInfo, CommandAction, ReturnSuccess, ReturnValue, UntaggedValue, Value};
|
||||
|
@ -11,6 +12,8 @@ pub struct Fetch {
|
|||
pub path: Option<Value>,
|
||||
pub tag: Tag,
|
||||
pub has_raw: bool,
|
||||
pub user: Option<String>,
|
||||
pub password: Option<String>,
|
||||
}
|
||||
|
||||
impl Fetch {
|
||||
|
@ -19,6 +22,8 @@ impl Fetch {
|
|||
path: None,
|
||||
tag: Tag::unknown(),
|
||||
has_raw: false,
|
||||
user: None,
|
||||
password: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,15 +42,30 @@ impl Fetch {
|
|||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
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_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 {
|
||||
return Err(e);
|
||||
|
@ -76,6 +96,8 @@ pub async fn fetch(
|
|||
location: &str,
|
||||
span: Span,
|
||||
has_raw: bool,
|
||||
user: Option<String>,
|
||||
password: Option<String>,
|
||||
) -> Result<(Option<String>, UntaggedValue, Tag), ShellError> {
|
||||
if url::Url::parse(location).is_err() {
|
||||
return Err(ShellError::labeled_error(
|
||||
|
@ -84,9 +106,16 @@ pub async fn fetch(
|
|||
span,
|
||||
));
|
||||
}
|
||||
|
||||
let response = surf::get(location).await;
|
||||
match response {
|
||||
let login = match (user, password) {
|
||||
(Some(user), Some(password)) => Some(encode(&format!("{}:{}", user, password))),
|
||||
(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") {
|
||||
Some(content_type) => {
|
||||
let content_type = Mime::from_str(content_type).map_err(|_| {
|
||||
|
|
|
@ -15,6 +15,18 @@ impl Plugin for Fetch {
|
|||
SyntaxShape::String,
|
||||
"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'))
|
||||
.filter())
|
||||
}
|
||||
|
@ -26,6 +38,8 @@ impl Plugin for Fetch {
|
|||
ShellError::labeled_error("internal error: path not set", "path not set", &self.tag)
|
||||
})?,
|
||||
self.has_raw,
|
||||
self.user.clone(),
|
||||
self.password.clone(),
|
||||
))])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue