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