http-fs 0.1.0

HTTP File Service library
Documentation
//!Hyper adaptor

use crate::config::{StaticFileConfig};
use super::ServeEntry;

use hyper::service::Service;
use futures::future::FutureResult;
use percent_encoding::{percent_decode};

use std::io;
use std::path::Path;
use std::borrow::Cow;

impl<C: StaticFileConfig> Service for super::StaticFiles<C> {
    type ReqBody = hyper::Body;
    type ResBody = hyper::Body;
    type Error = io::Error;
    type Future = FutureResult<hyper::Response<Self::ResBody>, Self::Error>;

    fn call(&mut self, req: hyper::Request<Self::ReqBody>) -> Self::Future {
        if !C::is_method_allowed(req.method()) {
            let res = hyper::Response::builder().status(http::StatusCode::METHOD_NOT_ALLOWED)
                                                .header(http::header::ALLOW, "GET, HEAD")
                                                .body(hyper::Body::empty())
                                                .expect("Create request with empty body");

            return futures::future::ok(res)
        }

        let path = req.uri().path().trim_start_matches("/");
        let path = percent_decode(path.as_bytes()).decode_utf8().expect("To percent decode");
        let path = &path;
        let path = match path {
            Cow::Borrowed(path) => Path::new(path),
            Cow::Owned(ref path) => Path::new(path),
        };
        let result = self.serve(&path);

        match result {
            ServeEntry::NotFound | ServeEntry::IoError(_) => {
                let res = hyper::Response::builder().status(http::StatusCode::NOT_FOUND)
                                                    .body(hyper::Body::empty())
                                                    .expect("Create request wtih empty body");
                futures::future::ok(res)
            },
            ServeEntry::Directory(path, dir) => {
                let res = hyper::Response::builder().status(http::StatusCode::OK)
                                                    .header(http::header::CONTENT_TYPE, http::header::HeaderValue::from_static("text/html; charset=utf-8"))
                                                    .body(self.list_dir(&path, dir).into())
                                                    .expect("Create request wtih empty body");
                futures::future::ok(res)
            },
            ServeEntry::File(file, meta) => {
                let mut response = hyper::Response::new(hyper::Body::empty());
                let (code, body) = self.serve_file(&path, file, meta, req.method().clone(), req.headers(), response.headers_mut());
                *response.status_mut() = code;

                if let Some(body) = body {
                    futures::future::ok(response.map(|_| hyper::Body::wrap_stream(body)))
                } else {
                    futures::future::ok(response)
                }
            }
        }
    }
}