1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::config::{StaticFileConfig};
use crate::ServeEntry;
use hyper::service::{MakeService, Service};
use futures::future::FutureResult;
use percent_encoding::{percent_decode};
use std::io;
use std::path::Path;
use std::borrow::Cow;
impl<C: StaticFileConfig + Clone, Ctx> MakeService<Ctx> for crate::StaticFiles<C> {
type ReqBody = hyper::Body;
type ResBody = hyper::Body;
type Error = io::Error;
type Service = Self;
type MakeError = io::Error;
type Future = FutureResult<Self::Service, Self::MakeError>;
fn make_service(&mut self, _: Ctx) -> Self::Future {
Ok(self.clone()).into()
}
}
impl<C: StaticFileConfig> Service for crate::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 mut response = hyper::Response::new(hyper::Body::empty());
let (code, body) = self.handle_not_found(&path, response.headers_mut());
*response.status_mut() = code;
if body.len() > 0 {
futures::future::ok(response.map(|_| hyper::Body::from(body)))
} else {
futures::future::ok(response)
}
},
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, path) => {
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)
}
}
}
}
}