aboutsummaryrefslogtreecommitdiffstats
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
parentInitial commit (diff)
downloadminiserve-36e006f8df4714f41d1e51824d0264680c8bf40f.tar.gz
miniserve-36e006f8df4714f41d1e51824d0264680c8bf40f.zip
Initial code checkin
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml62
-rw-r--r--Cargo.toml29
-rw-r--r--README.md10
-rw-r--r--index.html1
-rw-r--r--src/main.rs131
6 files changed, 234 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 50281a4..af26ef8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,6 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
+
+/target
+**/*.rs.bk
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6ac6c9b
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,62 @@
+language: rust
+cache: cargo
+
+rust:
+ - stable
+ - beta
+ - nightly
+
+addons:
+ apt:
+ packages:
+ - mingw-w64
+ - upx
+
+matrix:
+ include:
+ - env:
+ - TARGET=x86_64-unknown-linux-musl
+ - BIN_NAME=miniserve
+ - PROPER_NAME=miniserve-linux
+ os: linux
+ - env:
+ - TARGET=x86_64-pc-windows-gnu
+ - BIN_NAME=miniserve.exe
+ - PROPER_NAME=miniserve-win.exe
+ - RUSTFLAGS="-C linker=x86_64-w64-mingw32-gcc"
+ os: linux
+ - env:
+ - TARGET=x86_64-apple-darwin
+ - BIN_NAME=miniserve
+ - PROPER_NAME=miniserve-osx
+ os: osx
+
+before_install:
+ - rustup self update
+
+install:
+ # On Apple, the default target is already the right one.
+ - if [[ -n $TARGET && $TARGET != "x86_64-apple-darwin" ]]; then rustup target add $TARGET; fi
+
+script:
+ # If this is a normal, non-deployment build...
+ - if [[ -z $TARGET ]]; then cargo build --verbose; fi
+ - if [[ -n $TARGET ]]; then cargo build --verbose --release --target $TARGET; fi
+
+before_deploy:
+ # If this is a binary deployment...
+ - if [[ -n $TARGET ]]; then cp -a target/$TARGET/release/$BIN_NAME $PROPER_NAME && strip $PROPER_NAME; fi
+ - # Run upx on the binary if this is a deployment for Linux or Windows
+ - if [[ $TARGET = "x86_64-pc-windows-gnu" ]]; then upx $PROPER_NAME; fi
+ - if [[ $TARGET = "x86_64-unknown-linux-musl" ]]; then upx $PROPER_NAME; fi
+
+deploy:
+ - provider: releases
+ api_key:
+ secure: "n1OCiCjupkVieqsepGBOk6oxGcU89n9z0lQWWMAtBKREIEL1fnqt7A4z9FC1LV9UiAwvcvMHI8As5TA/7sV6jiWFuNOqu5HurX/n7cXlAuVWx00gCtWZ7Fh14ipVIDr2W52Mj/5qw1LSW19g8+9nLF1xO2YLrNpiaQX+V6Ypf04="
+ file: $PROPER_NAME
+ skip_cleanup: true
+ on:
+ branch: master
+ tags: true
+ condition: $TRAVIS_RUST_VERSION = stable && -n $TARGET
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..d1ed422
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "miniserve"
+version = "0.1.0"
+description = "For when you really just want to serve some files over HTTP right now!"
+authors = ["Sven-Hendrik Haase <svenstaro@gmail.com>"]
+repository = "https://github.com/svenstaro/miniserve"
+license = "MIT"
+readme = "README.md"
+keywords = ["serve", "http-server", "static-files"]
+categories = ["command-line-utilities", "command-line-interface"]
+
+[badges]
+travis-ci = { repository = "svenstaro/miniserve", branch = "master" }
+maintenance = { status = "actively-developed" }
+
+[dependencies]
+pbr = "1.0"
+yansi = "0.4"
+rand = "0.4"
+chrono = "0.4"
+url = "1.6"
+lazy_static = "1.0"
+humantime = "1.1"
+regex = "0.2.5"
+clap = "2.29"
+ctrlc = "3.1"
+actix = "0.5"
+actix-web = { git = "https://github.com/actix/actix-web.git" }
+simplelog = "0.5"
diff --git a/README.md b/README.md
index f180b55..7595257 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,8 @@
-# servethis
-:star2: For when you really just want to serve some files over HTTP right now!
+# miniserve - For when you really just want to serve some files over HTTP right now!
+
+[![Build Status](https://travis-ci.org/svenstaro/miniserve.svg?branch=master)](https://travis-ci.org/svenstaro/miniserve)
+[![AUR](https://img.shields.io/aur/version/miniserve.svg)](https://aur.archlinux.org/packages/miniserve/)
+[![Crates.io](https://img.shields.io/crates/v/miniserve.svg)](https://crates.io/crates/miniserve)
+[![dependency status](https://deps.rs/repo/github/svenstaro/miniserve/status.svg)](https://deps.rs/repo/github/svenstaro/miniserve)
+[![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/svenstaro/miniserve/blob/master/LICENSE)
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..ced54c9
--- /dev/null
+++ b/index.html
@@ -0,0 +1 @@
+rofl
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();
+}