nushell/crates/nu_plugin_s3/src/handler.rs
Antonio Yang 88555860f3
Fetch content from S3 (#2328)
* fetch content from s3 resource

* remove submodule

* fix clippy

* update Cargo.lock

* fix s3 plugin dependency version
2020-08-13 05:20:22 +12:00

134 lines
4 KiB
Rust

use nu_errors::ShellError;
use nu_protocol::{CallInfo, CommandAction, ReturnSuccess, ReturnValue, UntaggedValue, Value};
use nu_source::{AnchorLocation, Tag};
use s3handler::{CredentialConfig, Handler as S3Handler};
pub struct Handler {
pub resource: Option<Value>,
pub tag: Tag,
pub has_raw: bool,
pub config: CredentialConfig,
}
impl Handler {
pub fn new() -> Handler {
Handler {
tag: Tag::unknown(),
config: CredentialConfig {
host: String::new(),
access_key: String::new(),
secret_key: String::new(),
user: None,
region: None,
s3_type: None,
secure: None,
},
resource: None,
has_raw: false,
}
}
pub fn setup(&mut self, call_info: CallInfo) -> ReturnValue {
self.resource = {
let r = call_info.args.nth(0).ok_or_else(|| {
ShellError::labeled_error(
"No obj or directory specified",
"for command",
&call_info.name_tag,
)
})?;
Some(r.clone())
};
self.tag = call_info.name_tag.clone();
self.has_raw = call_info.args.has("raw");
if let Some(e) = call_info.args.get("endpoint") {
self.config.host = e.as_string()?
} else {
return Err(ShellError::labeled_error(
"No endpoint provided",
"for command",
&call_info.name_tag,
));
}
if let Some(access_key) = call_info.args.get("access_key") {
self.config.access_key = access_key.as_string()?
} else {
return Err(ShellError::labeled_error(
"No access key provided",
"for command",
&call_info.name_tag,
));
}
if let Some(secret_key) = call_info.args.get("secret_key") {
self.config.secret_key = secret_key.as_string()?
} else {
return Err(ShellError::labeled_error(
"No secret key provided",
"for command",
&call_info.name_tag,
));
}
if let Some(region) = call_info.args.get("region") {
self.config.region = Some(region.as_string()?)
}
ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value())
}
}
impl Default for Handler {
fn default() -> Self {
Self::new()
}
}
pub async fn s3_helper(resource: &Value, has_raw: bool, config: &CredentialConfig) -> ReturnValue {
let resource_str = resource.as_string()?;
let mut handler = S3Handler::from(config);
let (output, content_type) = handler
.cat(&resource_str)
.map_err(|e| ShellError::unexpected(e.to_string()))?;
let extension = if has_raw {
None
} else {
fn get_accept_ext(s: String) -> Option<String> {
if s.contains("json") {
Some("json".to_string())
} else if s.contains("xml") {
Some("xml".to_string())
} else if s.contains("svg") {
Some("svg".to_string())
} else if s.contains("html") {
Some("html".to_string())
} else {
None
}
}
// If the extension could not provide when uploading,
// try to use the resource extension.
content_type.and_then(get_accept_ext).or_else(|| {
resource_str
.split('.')
.last()
.map(String::from)
.and_then(get_accept_ext)
})
};
if let Some(e) = extension {
Ok(ReturnSuccess::Action(CommandAction::AutoConvert(
UntaggedValue::string(output).into_value(Tag {
span: resource.tag.span,
anchor: Some(AnchorLocation::Url(resource_str)),
}),
e,
)))
} else {
ReturnSuccess::value(UntaggedValue::string(output))
}
}