aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven-Hendrik Haase <svenstaro@gmail.com>2018-04-26 17:32:25 +0000
committerSven-Hendrik Haase <svenstaro@gmail.com>2018-04-26 17:32:25 +0000
commit36e006f8df4714f41d1e51824d0264680c8bf40f (patch)
treeccd085400e8d38d5e6be4ec4085447da9ea224b2 /src
parentInitial commit (diff)
downloadminiserve-36e006f8df4714f41d1e51824d0264680c8bf40f.tar.gz
miniserve-36e006f8df4714f41d1e51824d0264680c8bf40f.zip
Initial code checkin
Diffstat (limited to '')
-rw-r--r--src/main.rs131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..2e4a69f
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,131 @@
+extern crate actix;
+extern crate actix_web;
+extern crate simplelog;
+
+#[macro_use]
+extern crate clap;
+
+use actix_web::{server, App, fs, middleware, HttpRequest, HttpResponse, Result};
+use simplelog::{TermLogger, LevelFilter, Config};
+use std::path::PathBuf;
+use std::net::IpAddr;
+
+#[derive(Clone)]
+pub struct MiniserveConfig {
+ verbose: bool,
+ path: std::path::PathBuf,
+ port: u16,
+ interface: IpAddr,
+}
+
+fn is_valid_path(path: String) -> Result<(), String> {
+ let path_to_check = PathBuf::from(path);
+ if path_to_check.is_file() || path_to_check.is_dir() {
+ return Ok(());
+ }
+ Err(String::from("Path either doesn't exist or is not a regular file or a directory"))
+}
+
+fn is_valid_port(port: String) -> Result<(), String> {
+ port.parse::<u16>().and(Ok(())).or_else(|e| Err(e.to_string()))
+}
+
+fn is_valid_interface(interface: String) -> Result<(), String> {
+ interface.parse::<IpAddr>().and(Ok(())).or_else(|e| Err(e.to_string()))
+}
+
+pub fn parse_args() -> MiniserveConfig {
+ use clap::{App, Arg};
+
+ let matches = App::new(crate_name!())
+ .version(crate_version!())
+ .author(crate_authors!())
+ .about(crate_description!())
+ .arg(
+ Arg::with_name("verbose")
+ .short("v")
+ .long("verbose")
+ .help("Be verbose"),
+ )
+ .arg(
+ Arg::with_name("PATH")
+ .required(true)
+ .validator(is_valid_path)
+ .help("Which path to serve"),
+ )
+ .arg(
+ Arg::with_name("port")
+ .short("p")
+ .long("port")
+ .help("Port to use")
+ .validator(is_valid_port)
+ .required(false)
+ .default_value("8080")
+ .takes_value(true),
+ )
+ .arg(
+ Arg::with_name("interface")
+ .short("i")
+ .long("if")
+ .help("Interface to listen on")
+ .validator(is_valid_interface)
+ .required(false)
+ .default_value("0.0.0.0")
+ .takes_value(true),
+ )
+ .get_matches();
+
+ let verbose = matches.is_present("verbose");
+ let path = matches.value_of("PATH").unwrap();
+ let port = matches.value_of("port").unwrap().parse().unwrap();
+ let interface = matches.value_of("interface").unwrap().parse().unwrap();
+
+ MiniserveConfig {
+ verbose,
+ path: PathBuf::from(path),
+ port,
+ interface,
+ }
+}
+
+fn file_handler(req: HttpRequest<MiniserveConfig>) -> Result<fs::NamedFile> {
+ let path = &req.state().path;
+ Ok(fs::NamedFile::open(path)?)
+}
+
+fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
+ let s = {
+ let path = &app.state().path;
+ if path.is_file() {
+ None
+ } else {
+ Some(fs::StaticFiles::new(path).show_files_listing())
+ }
+ };
+
+ if let Some(s) = s {
+ app.handler("/", s)
+ } else {
+ app.resource("/", |r| r.f(file_handler))
+ }
+}
+
+fn main() {
+ let miniserve_config = parse_args();
+
+ if miniserve_config.verbose {
+ let _ = TermLogger::init(LevelFilter::Info, Config::default());
+ }
+ let sys = actix::System::new("miniserve");
+
+ let inside_config = miniserve_config.clone();
+ server::new(
+ move || App::with_state(inside_config.clone())
+ .middleware(middleware::Logger::default())
+ .configure(configure_app))
+ .bind(format!("{}:{}", &miniserve_config.interface, miniserve_config.port)).expect("Couldn't bind server")
+ .shutdown_timeout(1)
+ .start();
+
+ let _ = sys.run();
+}