Skip to content
Snippets Groups Projects
main.rs 4.31 KiB
Newer Older
#![feature(plugin)]
Louis's avatar
Louis committed
#![feature(alloc_system)]
#![plugin(rocket_codegen)]

Louis's avatar
Louis committed
extern crate alloc_system;
extern crate rocket;
extern crate docopt;
extern crate swerve;
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 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<TypedFile> {
    serve_files(None, args)
}

#[get("/<file..>")]
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 = args.get_dir().join(stub);

    let meta = match fs::metadata(&path) {
        Ok(metadata) => metadata,
        _ => return None,
    };

    if meta.is_dir() && !args.flag_no_index {
        Some(TypedFile::open(path.join("index.html"), None))
    } else {
        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, 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(config.server.threads);
    }

    if let Some(port) = args.flag_port {
        builder = builder.port(port);
    } else {
        builder = builder.port(config.server.port);
    }

    if let Some(address) = args.flag_address {
        builder = builder.address(address);
    } else {
        builder = builder.address(config.server.address);
    }

    builder.finalize().unwrap()
}

fn main() {
    let args: cli::Args = Docopt::new(cli::USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    if args.flag_help {
        println!("{}", cli::USAGE);
        process::exit(0);
    }

	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(server_config, false)
        .manage(args.clone())
        .manage(swerve_config);

	
    server = server.mount("/upload", routes![swerve::routing::mock_upload::to_file])
        .mount("/", routes![serve_root, serve_files]);

    if !args.flag_quiet {
        server = server.attach(rocket::fairing::AdHoc::on_launch(move |rckt| {
            let config = rckt.config();
            println!("\nSwerve is configured with {} worker threads", config.workers);
            println!("Swerving files from http://{}:{}\n", config.address, config.port);
        }))
        .attach(rocket::fairing::AdHoc::on_response(|req, _res| {
            println!("{} {}", req.method(), req.uri());
        }));
    }