-
Notifications
You must be signed in to change notification settings - Fork 324
/
Copy pathupload.rs
73 lines (60 loc) · 1.95 KB
/
upload.rs
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
use std::io::Error as IoError;
use std::path::Path;
use std::sync::Arc;
use async_std::{fs::OpenOptions, io};
use kv_log_macro::info;
use tempfile::TempDir;
use tide::prelude::*;
use tide::{Body, Request, Response, StatusCode};
#[derive(Clone)]
struct TempDirState {
tempdir: Arc<TempDir>,
}
impl TempDirState {
fn try_new() -> Result<Self, IoError> {
Ok(Self {
tempdir: Arc::new(tempfile::tempdir()?),
})
}
fn path(&self) -> &Path {
self.tempdir.path()
}
}
#[async_std::main]
async fn main() -> Result<(), IoError> {
femme::start();
let mut app = tide::with_state(TempDirState::try_new()?);
app.with(tide::log::LogMiddleware::new());
// To test this example:
// $ cargo run --example upload
// $ curl -T ./README.md localhost:8080 # this writes the file to a temp directory
// $ curl localhost:8080/README.md # this reads the file from the same temp directory
app.at(":file")
.put(|req: Request| async move {
let path = req.param("file")?;
let state = req.state::<TempDirState>();
let fs_path = state.path().join(path);
let file = OpenOptions::new()
.create(true)
.write(true)
.open(&fs_path)
.await?;
let bytes_written = io::copy(req, file).await?;
info!("file written", {
bytes: bytes_written,
path: fs_path.canonicalize()?.to_str()
});
Ok(json!({ "bytes": bytes_written }))
})
.get(|req: Request| async move {
let path = req.param("file")?;
let fs_path = req.state::<TempDirState>().path().join(path);
if let Ok(body) = Body::from_file(fs_path).await {
Ok(body.into())
} else {
Ok(Response::new(StatusCode::NotFound))
}
});
app.listen("127.0.0.1:8080").await?;
Ok(())
}