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
use md5::compute as compute_md5;
use tempfile::NamedTempFile;
use tiny_http::{Method, Request, Response};
use std::fs::{create_dir_all, remove_file, File};
use std::io::{Error, ErrorKind, Write};
use std::net::SocketAddr;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::thread;
fn req_handler(data_dir: &str, mut req: Request) {
let path = format!("{:x}", compute_md5(req.url().as_bytes()));
let mut body = String::new();
let _ = req.as_reader().read_to_string(&mut body);
let mut dest_path = PathBuf::from(data_dir);
dest_path.push(path.get(0..1).unwrap());
dest_path.push(path.get(1..2).unwrap());
dest_path.push(path.get(2..).unwrap());
let _ = match *req.method() {
Method::Get => {
let file = File::open(dest_path);
match file {
Ok(file) => req.respond(Response::from_file(file)),
Err(_) => req.respond(resp!("Server Error", 500)),
}
}
Method::Post | Method::Put => {
let tmpdir = Path::new(data_dir).join("tmp");
match NamedTempFile::new_in(tmpdir) {
Ok(mut tmpfile) => {
match tmpfile
.write(body.as_bytes())
.and(create_dir_all(dest_path.parent().unwrap()))
.and(
tmpfile
.persist(dest_path)
.map_err(|_| Error::new(ErrorKind::Other, "")),
) {
Ok(_) => req.respond(resp!("Inserted", 201)),
_ => req.respond(resp!("Unable to create file", 500)),
}
}
Err(_) => req.respond(resp!("Unable to create file", 500)),
}
}
Method::Delete => match remove_file(dest_path) {
Ok(_) => req.respond(resp!("Deleted", 204)),
Err(_) => req.respond(resp!("Unable to delete file", 500)),
},
_ => req.respond(resp!("Method not allowed", 405)),
};
}
pub fn start(port: u16, data_dir: String, threads: u16) {
let addr: SocketAddr = ([0, 0, 0, 0], port).into();
let server = Arc::new(tiny_http::Server::http(addr).unwrap());
let mut handles = Vec::new();
if create_dir_all(Path::new(&data_dir).join("tmp")).is_err() {
panic!("Could not create data dir. exiting\n");
}
let data_dir = Arc::new(data_dir);
for _ in 0..threads {
let server = server.clone();
let data_dir = data_dir.clone();
handles.push(thread::spawn(move || {
for rq in server.incoming_requests() {
req_handler(&data_dir, rq);
}
}));
}
for h in handles {
h.join().unwrap();
}
}