aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
authorSven-Hendrik Haase <svenstaro@gmail.com>2018-08-09 15:35:24 +0000
committerSven-Hendrik Haase <svenstaro@gmail.com>2018-08-09 15:35:24 +0000
commit6b6a7e306f8f83b1e092d147a0df117b375f32e1 (patch)
tree057201c19d311b20cac4e2a1d3ad17ac9f67d0be /src/main.rs
parentRun rustfmt (diff)
downloadminiserve-6b6a7e306f8f83b1e092d147a0df117b375f32e1.tar.gz
miniserve-6b6a7e306f8f83b1e092d147a0df117b375f32e1.zip
Update to actix 0.7 and add better output
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs86
1 files changed, 53 insertions, 33 deletions
diff --git a/src/main.rs b/src/main.rs
index d8c0f1d..ded331f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,6 +2,7 @@ extern crate actix;
extern crate actix_web;
extern crate base64;
extern crate simplelog;
+extern crate yansi;
#[macro_use]
extern crate clap;
@@ -9,8 +10,12 @@ use actix_web::http::header;
use actix_web::middleware::{Middleware, Response};
use actix_web::{fs, middleware, server, App, HttpMessage, HttpRequest, HttpResponse, Result};
use simplelog::{Config, LevelFilter, TermLogger};
+use std::io::{self, Write};
use std::net::{IpAddr, Ipv4Addr};
use std::path::PathBuf;
+use std::thread;
+use std::time::Duration;
+use yansi::{Color, Paint};
enum BasicAuthError {
Base64DecodeError,
@@ -30,6 +35,7 @@ pub struct MiniserveConfig {
port: u16,
interface: IpAddr,
auth: Option<BasicAuthParams>,
+ path_explicitly_chosen: bool,
}
/// Decode a HTTP basic auth string into a tuple of username and password.
@@ -90,14 +96,12 @@ pub fn parse_args() -> MiniserveConfig {
.short("v")
.long("verbose")
.help("Be verbose"),
- )
- .arg(
+ ).arg(
Arg::with_name("PATH")
- .required(true)
+ .required(false)
.validator(is_valid_path)
.help("Which path to serve"),
- )
- .arg(
+ ).arg(
Arg::with_name("port")
.short("p")
.long("port")
@@ -106,8 +110,7 @@ pub fn parse_args() -> MiniserveConfig {
.required(false)
.default_value("8080")
.takes_value(true),
- )
- .arg(
+ ).arg(
Arg::with_name("interface")
.short("i")
.long("if")
@@ -116,19 +119,17 @@ pub fn parse_args() -> MiniserveConfig {
.required(false)
.default_value("0.0.0.0")
.takes_value(true),
- )
- .arg(
+ ).arg(
Arg::with_name("auth")
.short("a")
.long("auth")
.validator(is_valid_auth)
.help("Set authentication (username:password)")
.takes_value(true),
- )
- .get_matches();
+ ).get_matches();
let verbose = matches.is_present("verbose");
- let path = matches.value_of("PATH").unwrap();
+ let path = matches.value_of("PATH");
let port = matches.value_of("port").unwrap().parse().unwrap();
let interface = matches.value_of("interface").unwrap().parse().unwrap();
let auth = if let Some(auth_split) = matches.value_of("auth").map(|x| x.splitn(2, ':')) {
@@ -147,14 +148,15 @@ pub fn parse_args() -> MiniserveConfig {
MiniserveConfig {
verbose,
- path: PathBuf::from(path),
+ path: PathBuf::from(path.unwrap_or(".")),
port,
interface,
auth,
+ path_explicitly_chosen: path.is_some(),
}
}
-fn file_handler(req: HttpRequest<MiniserveConfig>) -> Result<fs::NamedFile> {
+fn file_handler(req: &HttpRequest<MiniserveConfig>) -> Result<fs::NamedFile> {
let path = &req.state().path;
Ok(fs::NamedFile::open(path)?)
}
@@ -165,7 +167,11 @@ fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
if path.is_file() {
None
} else {
- Some(fs::StaticFiles::new(path).show_files_listing())
+ Some(
+ fs::StaticFiles::new(path)
+ .expect("Couldn't create path")
+ .show_files_listing(),
+ )
}
};
@@ -179,11 +185,7 @@ fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
struct Auth;
impl Middleware<MiniserveConfig> for Auth {
- fn response(
- &self,
- req: &mut HttpRequest<MiniserveConfig>,
- resp: HttpResponse,
- ) -> Result<Response> {
+ fn response(&self, req: &HttpRequest<MiniserveConfig>, resp: HttpResponse) -> Result<Response> {
if let Some(ref required_auth) = req.state().auth {
if let Some(auth_headers) = req.headers().get(header::AUTHORIZATION) {
let auth_req = match parse_basic_auth(auth_headers) {
@@ -211,8 +213,7 @@ impl Middleware<MiniserveConfig> for Auth {
.header(
header::WWW_AUTHENTICATE,
header::HeaderValue::from_static("Basic realm=\"miniserve\""),
- )
- .finish();
+ ).finish();
return Ok(Response::Done(new_resp));
}
}
@@ -221,6 +222,10 @@ impl Middleware<MiniserveConfig> for Auth {
}
fn main() {
+ if cfg!(windows) && !Paint::enable_windows_ascii() {
+ Paint::disable();
+ }
+
let miniserve_config = parse_args();
if miniserve_config.verbose {
@@ -237,10 +242,9 @@ fn main() {
}).bind(format!(
"{}:{}",
&miniserve_config.interface, miniserve_config.port
- ))
- .expect("Couldn't bind server")
- .shutdown_timeout(0)
- .start();
+ )).expect("Couldn't bind server")
+ .shutdown_timeout(0)
+ .start();
// If the interface is 0.0.0.0, we'll change it to localhost so that clicking the link will
// also work on Windows. Why can't Windows interpret 0.0.0.0?
@@ -251,14 +255,30 @@ fn main() {
};
let canon_path = miniserve_config.path.canonicalize().unwrap();
+ let path_string = canon_path.to_string_lossy();
+
+ if !miniserve_config.path_explicitly_chosen {
+ println!("{info} miniserve has been invoked without an explicit path so it will serve the current directory.", info=Paint::blue("Info:").bold());
+ println!(
+ " Invoke with -h|--help to see options or invoke as `miniserve .` to hide this advice."
+ );
+ print!("Starting server in ");
+ io::stdout().flush().unwrap();
+ for c in "3… 2… 1… \n".chars() {
+ print!("{}", c);
+ io::stdout().flush().unwrap();
+ thread::sleep(Duration::from_millis(500));
+ }
+ }
println!(
- "miniserve is serving your files at http://{interface}:{port}",
- interface = interface,
- port = miniserve_config.port
- );
- println!(
- "Currently serving path {path}",
- path = canon_path.to_string_lossy()
+ "miniserve is serving path {path} at {address}",
+ path = Color::Yellow.paint(path_string).bold(),
+ address = Color::Green
+ .paint(format!(
+ "http://{interface}:{port}",
+ interface = interface,
+ port = miniserve_config.port
+ )).bold()
);
println!("Quit by pressing CTRL-C");