-
Notifications
You must be signed in to change notification settings - Fork 1
/
demo_format.rs
129 lines (110 loc) · 3.58 KB
/
demo_format.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
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
118
119
120
121
122
123
124
125
126
127
128
129
use actix_files::Files;
use actix_multipart::Multipart;
use actix_web::{
get, middleware::Logger,
post, web,
App, Error, HttpResponse, HttpServer, Responder,
};
use futures_util::stream::StreamExt as _;
use uuid::Uuid;
use std::fs::read;
use std::io::Write;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
#[cfg(windows)]
use std::os::windows::fs::MetadataExt;
#[get("/{route}")]
async fn index_routes() -> impl Responder {
HttpResponse::Ok()
.body(read("./build/index.html")
.unwrap())
}
#[get("/")]
async fn index() -> impl Responder {
HttpResponse::Ok()
.body(read("./build/index.html").unwrap())
}
#[post("/upload/")]
async fn upload(mut payload: Multipart) -> Result<HttpResponse, Error> {
// iterate over multipart stream
log::warn!("/upload/ was called!");
while let Some(Ok(mut field)) = payload.next().await {
// A multipart/form-data stream has to contain `content_disposition`
let content_disposition = field.content_disposition();
let filename = content_disposition
.get_filename()
.map_or_else(|| Uuid::new_v4().to_string(), sanitize_filename::sanitize);
let filepath = format!("./uploads/{}", filename);
// File::create is blocking operation, use threadpool
let mut f = web::block(|| std::fs::File::create(filepath)).await??;
// Field in turn is stream of *Bytes* object
while let Some(Ok(chunk)) = field.next().await {
// filesystem operations are blocking, we have to use threadpool
f = web::block(move || f.write_all(&chunk).map(|_| f)).await??;
}
}
Ok(HttpResponse::Found()
.append_header(("Location", "/dashboard"))
.finish())
}
#[get("/list/")]
async fn uploads(_: String) -> web::Json<Vec<(String, usize)>> {
let mut files = vec![];
for file in std::fs::read_dir("uploads/").unwrap() {
let file = file.unwrap();
#[cfg(windows)]
let file_size = file.metadata().unwrap().file_size();
#[cfg(unix)]
let file_size = file.metadata().unwrap().size();
files.push((
file.file_name().to_str().unwrap().to_string(),
(file_size / 1024) as usize,
))
}
web::Json(files)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
log::info!("starting HTTP server at http://localhost:8000");
HttpServer::new(|| {
App::new()
// .wrap(Cors::permissive())
.service(index)
.service(index_routes)
.service(Files::new("/static", "./build/static"))
.service(upload)
.service(uploads)
.service(Files::new("/download/", "./uploads/"))
.wrap(Logger::default())
})
.bind(("127.0.0.1", 8000))?
.run()
.await
}
use cookie::{Cookie, CookieJar};
fn use_cookie_without_secure() {
let mut c = Cookie::new("name", "value");
c.set_secure(true);
c.set_secure(false);
}
fn use_cookie_builder_without_secure() {
Cookie::build("name", "value").secure(true);
Cookie::build("name", "value").secure(false);
}
fn use_cookie_without_http_only() {
let mut c = Cookie::new("name", "value");
c.set_http_only(true);
c.set_http_only(false);
}
fn use_cookie_builder_without_http_only() {
Cookie::build("name",
"value").http_only(true);
Cookie::build("name", "value").http_only(false);
}
fn header() {
use http::header::{HeaderMap, SERVER, SET_COOKIE};
let mut h = HeaderMap::new();
h.insert(SERVER, 5.into());
h.insert(SET_COOKIE, 42.into());
}