Initial code checkin

This commit is contained in:
Sven-Hendrik Haase 2018-04-26 19:32:25 +02:00
parent 0938d69f9a
commit 36e006f8df
6 changed files with 234 additions and 2 deletions

3
.gitignore vendored
View File

@ -8,3 +8,6 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
/target
**/*.rs.bk

62
.travis.yml Normal file
View File

@ -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

29
Cargo.toml Normal file
View File

@ -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"

View File

@ -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)

1
index.html Normal file
View File

@ -0,0 +1 @@
rofl

131
src/main.rs Normal file
View File

@ -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();
}