Why am I fighting the compiler? - Wrote this, which works, but I feel like I'm breaking every rule in the book:
#[macro_use]
extern crate lazy_static;
use std::ffi::OsString;
use std::path::PathBuf;
use std::str::FromStr;
use actix_rt;
use actix_web::client::Client;
use async_std::fs::File;
use async_std::prelude::*;
use http::uri::Uri;
// Result<OsString, (SendRequestError|std::core::convert::Infallible|actix_http::error::PayloadError)
#[actix_rt::main]
async fn download(uri: &'static str, target_dir: &'static str) -> Result<OsString, ()> {
let client = Client::default();
let uri = Uri::from_str(uri).unwrap();
// Create request builder and send request
let response = client
.get(&uri)
.header("User-Agent", "Actix-web")
.send()
.await; // <- Send http request
println!("Response: {:?}", response);
let get_host = || uri.host().unwrap().to_owned();
let path = match &uri.path_and_query() {
Some(path_and_query) => {
let p = path_and_query.path().to_owned();
if p == "/" {
get_host()
} else {
p
}
}
None => get_host(),
};
let output_pathbuf = PathBuf::from_str(target_dir).unwrap().join(path);
let output_file = output_pathbuf.as_os_str();
let mut file = File::create(output_file).await.unwrap();
file.write_all(&response.unwrap().body().await.unwrap())
.await
.unwrap();
// file.write_all(b"Hello, world!").await.unwrap();
return Ok(output_file.to_owned());
}
#[cfg(test)]
mod tests {
use std::borrow::Borrow;
// use std::env::temp_dir;
use std::fs::create_dir_all;
use std::path::PathBuf;
use std::str::FromStr;
use crate::download;
fn temp_dir() -> PathBuf {
return PathBuf::from_str("/tmp").unwrap();
}
lazy_static! {
pub static ref TEMP_DIR: PathBuf = temp_dir().join(module_path!());
pub static ref TEMP_DIR_O: Option<&'static str> = TEMP_DIR.to_str();
pub static ref TEMP_DIR_S: &'static str = TEMP_DIR_O.unwrap();
}
#[test]
fn test_download() {
if !TEMP_DIR.exists() {
create_dir_all(TEMP_DIR.borrow() as &PathBuf).unwrap();
}
//let output_dir =
download(
"http://www.rust-lang.org",
TEMP_DIR_S.borrow() as &'static str,
)
.unwrap();
//assert_eq!(output_dir, "foo")
}
}
Remarks:
- I understand that
unwrap()
is frowned upon, and should be replaced by error percolation (?
sugar) and handled at the topmost level (that makes sense). Replacing the unwraps, and now it can return any ofSendRequestError|std::core::convert::Infallible|actix_http::error::PayloadError
. Should IBox
/dyn
astd::Error
, create a bigfailure
enum
, or something cleaner? - Not so happy with the types. I tried working with
AsRef<PathBuf>
,Into<Uri>
, and variants thereof. Clearly that doesn't work. - How do I get the
Result
? - This is the first step in a multi-URL downloader, but I am worried about efficiency. Do I setup some sort of executor/reactor system atop async/await concepts?
PS: Originally posted error handling - HTTP download function in Rust (async/await) - Code Review Stack Exchange
Thanks for your review