clippy and rustfmt anoyances
This commit is contained in:
parent
c68cf3a3e8
commit
da69d3de6f
3 changed files with 103 additions and 54 deletions
55
src/main.rs
55
src/main.rs
|
@ -3,28 +3,34 @@ mod web;
|
|||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let app = clap::App::new(clap::crate_name!())
|
||||
.author(clap::crate_authors!("\n"))
|
||||
.version(clap::crate_version!())
|
||||
.about(clap::crate_description!())
|
||||
.arg(clap::Arg::with_name("chdir")
|
||||
.short("w")
|
||||
.long("chdir")
|
||||
.value_name("DIRECTORY")
|
||||
.help("directory to serve")
|
||||
.default_value(".")
|
||||
.takes_value(true))
|
||||
.arg(clap::Arg::with_name("addr")
|
||||
.short("b")
|
||||
.long("bind")
|
||||
.value_name("ADDRESS")
|
||||
.help("bind address")
|
||||
.default_value("0.0.0.0")
|
||||
.takes_value(true))
|
||||
.arg(clap::Arg::with_name("port")
|
||||
.value_name("PORT")
|
||||
.help("Specify alternate port")
|
||||
.default_value("8000")
|
||||
.index(1));
|
||||
.author(clap::crate_authors!("\n"))
|
||||
.version(clap::crate_version!())
|
||||
.about(clap::crate_description!())
|
||||
.arg(
|
||||
clap::Arg::with_name("chdir")
|
||||
.short("w")
|
||||
.long("chdir")
|
||||
.value_name("DIRECTORY")
|
||||
.help("directory to serve")
|
||||
.default_value(".")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::with_name("addr")
|
||||
.short("b")
|
||||
.long("bind")
|
||||
.value_name("ADDRESS")
|
||||
.help("bind address")
|
||||
.default_value("0.0.0.0")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::with_name("port")
|
||||
.value_name("PORT")
|
||||
.help("Specify alternate port")
|
||||
.default_value("8000")
|
||||
.index(1),
|
||||
);
|
||||
let matches = app.get_matches();
|
||||
|
||||
let chdir = matches.value_of("chdir").unwrap(); // these shouldn't panic ever, since all have default_value
|
||||
|
@ -32,7 +38,10 @@ fn main() -> std::io::Result<()> {
|
|||
let port = matches.value_of("port").unwrap();
|
||||
let bind_addr = format!("{}:{}", addr, port);
|
||||
|
||||
std::env::set_var("RUST_LOG", std::env::var("RUST_LOG").unwrap_or("info".to_string()));
|
||||
std::env::set_var(
|
||||
"RUST_LOG",
|
||||
std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()),
|
||||
);
|
||||
env_logger::init();
|
||||
|
||||
let root = std::path::PathBuf::from(chdir).canonicalize()?;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use bytes;
|
||||
use futures;
|
||||
use futures::Sink;
|
||||
use bytes;
|
||||
use tar;
|
||||
|
||||
use std::thread;
|
||||
use std::path::PathBuf;
|
||||
use std::io;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::thread;
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
|
@ -17,7 +16,6 @@ type Stream = futures::sync::mpsc::Receiver<bytes::Bytes>;
|
|||
type Sender = futures::sync::mpsc::Sender<bytes::Bytes>;
|
||||
type BlockingSender = futures::sink::Wait<Sender>;
|
||||
|
||||
|
||||
pub fn stream_tar_in_thread(path: PathBuf) -> Stream {
|
||||
let (writer, stream) = StreamWriter::new(64);
|
||||
|
||||
|
@ -27,32 +25,34 @@ pub fn stream_tar_in_thread(path: PathBuf) -> Stream {
|
|||
a.mode(tar::HeaderMode::Deterministic);
|
||||
a.append_dir_all(last_path_component, &path)
|
||||
.unwrap_or_else(|e| println!("{}", e));
|
||||
a.finish()
|
||||
.unwrap_or_else(|e| println!("{}", e));
|
||||
a.finish().unwrap_or_else(|e| println!("{}", e));
|
||||
});
|
||||
stream
|
||||
}
|
||||
|
||||
struct StreamWriter {
|
||||
tx: BlockingSender
|
||||
tx: BlockingSender,
|
||||
}
|
||||
|
||||
impl StreamWriter {
|
||||
fn new(size: usize) -> (Self, Stream) {
|
||||
let (tx, rx) = futures::sync::mpsc::channel(size);
|
||||
let tx = tx.wait();
|
||||
(StreamWriter{tx:tx}, rx)
|
||||
(StreamWriter { tx }, rx)
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for StreamWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.tx.send(bytes::Bytes::from(buf))
|
||||
self.tx
|
||||
.send(bytes::Bytes::from(buf))
|
||||
.map(|_| buf.len())
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.tx.flush().map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
self.tx
|
||||
.flush()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
}
|
||||
}
|
||||
|
|
80
src/web.rs
80
src/web.rs
|
@ -1,6 +1,6 @@
|
|||
use actix_web::{App, middleware, error, HttpServer, HttpRequest, HttpResponse, Responder, web};
|
||||
use actix_web::dev::ServiceResponse;
|
||||
use actix_files as fs;
|
||||
use actix_web::dev::ServiceResponse;
|
||||
use actix_web::{error, middleware, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
|
||||
use futures::Stream;
|
||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
use v_htmlescape::escape as escape_html_entity;
|
||||
|
@ -10,7 +10,6 @@ use crate::threaded_archiver;
|
|||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
pub fn run(bind_addr: &str, root: &PathBuf) -> std::io::Result<()> {
|
||||
let root = root.clone();
|
||||
HttpServer::new(move || {
|
||||
|
@ -32,49 +31,88 @@ pub fn run(bind_addr: &str, root: &PathBuf) -> std::io::Result<()> {
|
|||
.run()
|
||||
}
|
||||
|
||||
|
||||
fn handle_directory<'a, 'b>(
|
||||
dir: &'a fs::Directory,
|
||||
req: &'b HttpRequest,
|
||||
fn handle_directory(
|
||||
dir: &fs::Directory,
|
||||
req: &HttpRequest,
|
||||
) -> Result<ServiceResponse, std::io::Error> {
|
||||
|
||||
let rd = std::fs::read_dir(&dir.path)?;
|
||||
|
||||
fn optimistic_is_dir(entry: &std::fs::DirEntry) -> bool {
|
||||
// consider it non directory if metadata reading fails, better than an unwrap() panic
|
||||
entry.metadata().map(|m| m.file_type().is_dir()).unwrap_or(false)
|
||||
entry
|
||||
.metadata()
|
||||
.map(|m| m.file_type().is_dir())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
let mut paths : Vec<_> = rd.filter_map(|entry| if dir.is_visible(&entry) { entry.ok() } else {None}).collect();
|
||||
let mut paths: Vec<_> = rd
|
||||
.filter_map(|entry| {
|
||||
if dir.is_visible(&entry) {
|
||||
entry.ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
paths.sort_by_key(|entry| (!optimistic_is_dir(entry), entry.file_name()));
|
||||
|
||||
|
||||
let tar_url = req.path().trim_end_matches('/'); // this is already encoded
|
||||
|
||||
let mut body = String::new();
|
||||
writeln!(body, "<h1>Index of {}</h1>", req.path()).unwrap(); // FIXME: decode from url, escape for html
|
||||
writeln!(body, r#"<small>[<a href="{}.tar">.tar</a> of whole directory]</small>"#, tar_url).unwrap();
|
||||
writeln!(
|
||||
body,
|
||||
r#"<small>[<a href="{}.tar">.tar</a> of whole directory]</small>"#,
|
||||
tar_url
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(body, "<table>").unwrap();
|
||||
writeln!(body, "<tr><td>📁 <a href='../'>../</a></td><td>Size</td></tr>").unwrap();
|
||||
writeln!(
|
||||
body,
|
||||
"<tr><td>📁 <a href='../'>../</a></td><td>Size</td></tr>"
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
for entry in paths {
|
||||
let meta = entry.metadata()?;
|
||||
let file_url = utf8_percent_encode(&entry.file_name().to_string_lossy(), NON_ALPHANUMERIC).to_string();
|
||||
let file_url =
|
||||
utf8_percent_encode(&entry.file_name().to_string_lossy(), NON_ALPHANUMERIC).to_string();
|
||||
let file_name = escape_html_entity(&entry.file_name().to_string_lossy()).to_string();
|
||||
let size = meta.len();
|
||||
|
||||
write!(body, "<tr>").unwrap();
|
||||
if meta.file_type().is_dir() {
|
||||
writeln!(body, r#"<td>📂 <a href="{}/">{}/</a></td>"#, file_url, file_name).unwrap();
|
||||
write!(body, r#" <td><small>[<a href="{}.tar">.tar</a>]</small></td>"#, file_url).unwrap();
|
||||
writeln!(
|
||||
body,
|
||||
r#"<td>📂 <a href="{}/">{}/</a></td>"#,
|
||||
file_url, file_name
|
||||
)
|
||||
.unwrap();
|
||||
write!(
|
||||
body,
|
||||
r#" <td><small>[<a href="{}.tar">.tar</a>]</small></td>"#,
|
||||
file_url
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
writeln!(body, r#"<td>🗎 <a href="{}">{}</a></td>"#, file_url, file_name).unwrap();
|
||||
writeln!(
|
||||
body,
|
||||
r#"<td>🗎 <a href="{}">{}</a></td>"#,
|
||||
file_url, file_name
|
||||
)
|
||||
.unwrap();
|
||||
write!(body, " <td>{}</td>", size).unwrap();
|
||||
}
|
||||
writeln!(body, "</tr>").unwrap();
|
||||
}
|
||||
writeln!(body, "</table>").unwrap();
|
||||
writeln!(body, r#"<footer><a href="{}">{} {}</a></footer>"#,
|
||||
env!("CARGO_PKG_HOMEPAGE"), env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")).unwrap();
|
||||
writeln!(
|
||||
body,
|
||||
r#"<footer><a href="{}">{} {}</a></footer>"#,
|
||||
env!("CARGO_PKG_HOMEPAGE"),
|
||||
env!("CARGO_PKG_NAME"),
|
||||
env!("CARGO_PKG_VERSION")
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut html = String::new();
|
||||
writeln!(html, "<!DOCTYPE html>").unwrap();
|
||||
|
@ -85,7 +123,9 @@ fn handle_directory<'a, 'b>(
|
|||
writeln!(html, "<body>\n{}</body>", body).unwrap();
|
||||
writeln!(html, "</html>").unwrap();
|
||||
|
||||
let resp = HttpResponse::Ok().content_type("text/html; charset=utf-8").body(html);
|
||||
let resp = HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(html);
|
||||
|
||||
Ok(ServiceResponse::new(req.clone(), resp))
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue