Skip to content
Snippets Groups Projects
Unverified Commit 9f509c0a authored by Louis's avatar Louis :fire:
Browse files

Update versions, merge file config with cli config, file upload routing

parent 22602d57
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
......@@ -13,7 +13,7 @@ license = "GPL-3.0+"
categories = ["command-line-utilities", "web-programming::http-server"]
keywords = ["file-server", "executable"]
exlude = [
exclude = [
".travis.yml",
"example/*",
]
......@@ -26,11 +26,14 @@ lto = true
[dependencies]
rocket = "0.3.3"
rocket_codegen = "0.3.3"
rocket_contrib = "0.3.3"
rocket = "0.3.8"
rocket_codegen = "0.3.8"
rocket_contrib = "0.3.8"
serde = "1"
serde_derive = "1"
docopt = "0.8"
formdata = "0.12.2"
hyper = "0.10"
\ No newline at end of file
hyper = "0.10"
rand = "0.3"
rhai = "0.7"
serde_yaml = "0.7.3"
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_yaml;
extern crate rhai;
extern crate rocket;
extern crate rocket_contrib;
extern crate formdata;
extern crate hyper;
extern crate rand;
pub mod scripting;
pub mod cli;
pub mod routing;
\ No newline at end of file
......@@ -6,30 +6,62 @@ extern crate alloc_system;
extern crate rocket;
extern crate docopt;
extern crate swerve;
extern crate rhai;
use std::{path, fs, process};
use rhai::Engine;
use std::{path, process, io};
use std::fs::{self, File};
use docopt::Docopt;
use rocket::response::NamedFile;
use rocket::http::ContentType;
use rocket::{Response, Request};
use swerve::cli;
use swerve::routing;
use swerve::scripting;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use rocket::response::Responder;
struct TypedFile {
file: File,
content_type: Option<ContentType>,
path: PathBuf,
}
impl TypedFile {
pub fn open<P: AsRef<Path>>(path: P, content_type: Option<rocket::http::ContentType>) -> TypedFile {
let file = File::open(path.as_ref()).unwrap();
TypedFile { file, content_type, path: (*path.as_ref()).to_path_buf() }
}
}
impl rocket::response::Responder<'static> for TypedFile {
fn respond_to(self, _: &Request) -> Result<Response<'static>, rocket::http::Status> {
let mut response = Response::new();
if let Some(content_type) = self.content_type {
response.set_header(content_type);
} else {
response.set_header(ContentType::from_extension(&self.path.extension().unwrap().to_string_lossy()).unwrap());
}
response.set_streamed_body(BufReader::new(self.file));
Ok(response)
}
}
#[get("/")]
fn serve_root(args: rocket::State<cli::Args>) -> Option<NamedFile> {
fn serve_root(args: rocket::State<cli::Args>) -> Option<TypedFile> {
serve_files(None, args)
}
#[get("/<file..>")]
fn serve_files(file: Option<path::PathBuf>, args: rocket::State<cli::Args>) -> Option<NamedFile> {
fn serve_files(file: Option<path::PathBuf>, args: rocket::State<cli::Args>) -> Option<TypedFile> {
let stub = match file {
Some(path) => path,
None => path::PathBuf::from(""),
};
let path = match args.flag_dir {
Some(ref root) => path::PathBuf::from(root).join(stub),
None => stub,
};
let path = args.get_dir().join(stub);
let meta = match fs::metadata(&path) {
Ok(metadata) => metadata,
......@@ -37,30 +69,34 @@ fn serve_files(file: Option<path::PathBuf>, args: rocket::State<cli::Args>) -> O
};
if meta.is_dir() && !args.flag_no_index {
NamedFile::open(path.join("index.html")).ok()
Some(TypedFile::open(path.join("index.html"), None))
} else {
NamedFile::open(path).ok()
if &path.extension().unwrap().to_string_lossy() == "wasm" {
Some( TypedFile::open(path, Some(ContentType::new("application", "wasm"))))
} else {
Some(TypedFile::open(path, None))
}
}
}
fn config_from_args(args: cli::Args) -> rocket::Config {
fn config_from_args(args: cli::Args, config: cli::SwerveConfig) -> rocket::Config {
let mut builder = rocket::Config::build(rocket::config::Environment::Development);
if let Some(threads) = args.flag_threads {
builder = builder.workers(threads);
} else {
builder = builder.workers(32);
builder = builder.workers(config.server.threads);
}
if let Some(port) = args.flag_port {
builder = builder.port(port);
} else {
builder = builder.port(8200);
builder = builder.port(config.server.port);
}
if let Some(address) = args.flag_address {
builder = builder.address(address);
} else {
builder = builder.address("localhost");
builder = builder.address(config.server.address);
}
builder.finalize().unwrap()
......@@ -76,11 +112,25 @@ fn main() {
process::exit(0);
}
let config = config_from_args(args.clone());
if args.flag_license {
cli::gpl::show_license_and_exit();
}
let config_path = args.get_dir().join(".swerve/config.yml");
let swerve_config = cli::SwerveConfig::from_file(&config_path).unwrap_or_else(|e| {
println!("Error in config file {} | {}", config_path.to_string_lossy(), e);
std::process::exit(2);
});
let server_config = config_from_args(args.clone(), swerve_config.clone());
println!("{:?}", swerve_config);
let mut server = rocket::custom(config, false)
let mut server = rocket::custom(server_config, false)
.manage(args.clone())
.mount("/upload", routes![swerve::routing::mock_upload::to_file])
.manage(swerve_config);
server = server.mount("/upload", routes![swerve::routing::mock_upload::to_file])
.mount("/", routes![serve_root, serve_files]);
if !args.flag_quiet {
......@@ -93,6 +143,7 @@ fn main() {
println!("{} {}", req.method(), req.uri());
}));
}
server.launch();
{
server.launch();
}
}
\ No newline at end of file
use rocket::Data;
use rocket::{Data, State};
use formdata::{read_formdata};
use routing::request::ConvertedHeaders;
use hyper::header::{Headers, ContentDisposition};
use hyper::header::{Headers, ContentDisposition, DispositionParam};
use rocket::request::FromRequest;
use std::io::{Read, Write, copy};
use std::io::{BufReader, BufWriter};
use std::fs::{OpenOptions, File};
use std::fs::{OpenOptions, File, create_dir};
use cli::{HandlerMethod, SwerveConfig};
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use rand::{Rng, StdRng};
#[post(path = "/", data = "<upload>")]
pub fn to_file(headers: ConvertedHeaders, upload: Data) -> String {
pub fn to_file(headers: ConvertedHeaders, conf: State<SwerveConfig>, upload: Data) -> Result<String, String> {
let formdata = read_formdata(&mut upload.open(), &headers.as_hyper());
if let Ok(data) = formdata {
let fields = collect_fields(data.fields);
match conf.field_handling {
HandlerMethod::Log => println!("{:?}", fields),
HandlerMethod::File => println!("{:?}", fields),
}
create_dir("uploads");
for file in data.files {
let (fieldname, fieldvalue) = file;
if fieldname == String::from("upload") {
let mut input = File::open(fieldvalue.path.clone()).unwrap();
let mut output = OpenOptions::new().write(true).open("upload_data").unwrap();
let (name, value) = file;
if name == String::from("upload") {
let content_disposition = value.headers.get::<ContentDisposition>().unwrap();
let file_name = filename_from_disposition(content_disposition);
let mut input = File::open(value.path.clone()).unwrap();
let mut output = OpenOptions::new()
.write(true)
.create(true)
.open(PathBuf::from("uploads").join(file_name.clone().unwrap_or(String::from("upload_data"))))
.unwrap();
copy(&mut input, &mut output).unwrap();
println!("File written to {}", file_name.unwrap());
}
}
String::from("Complete")
Ok(String::from("Complete"))
} else {
String::from("Failed")
Err(String::from("Failed"))
}
}
fn collect_fields(fields: Vec<(String, String)>) -> HashMap<String, String> {
let mut map = HashMap::with_capacity(fields.len());
'collector: for (key, value) in fields {
if value == String::from("undefined") { continue 'collector };
map.insert(key.clone(), value.clone());
}
map
}
fn filename_from_disposition(dispo: &ContentDisposition) -> Option<String> {
for param in dispo.parameters.iter() {
if let &DispositionParam::Filename(_, _, ref name_vec) = param {
return Some(String::from_utf8(name_vec.to_vec()).unwrap_or(String::from("bad_filename.bin")));
}
}
None
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment