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
use http_service::Body;
use multipart::server::Multipart;
use std::io::Cursor;
use crate::{
error::{BoxTryFuture, ResultExt},
Context, Response,
};
pub trait ExtractForms {
fn body_form<T: serde::de::DeserializeOwned>(&mut self) -> BoxTryFuture<T>;
fn body_multipart(&mut self) -> BoxTryFuture<Multipart<Cursor<Vec<u8>>>>;
}
impl<AppData: Send + Sync + 'static> ExtractForms for Context<AppData> {
fn body_form<T: serde::de::DeserializeOwned>(&mut self) -> BoxTryFuture<T> {
let body = self.take_body();
box_async! {
let body = await!(body.into_vec()).client_err()?;
Ok(serde_urlencoded::from_bytes(&body).map_err(|e| err_fmt!("could not decode form: {}", e)).client_err()?)
}
}
fn body_multipart(&mut self) -> BoxTryFuture<Multipart<Cursor<Vec<u8>>>> {
const BOUNDARY: &str = "boundary=";
let boundary = self.headers().get("content-type").and_then(|ct| {
let ct = ct.to_str().ok()?;
let idx = ct.find(BOUNDARY)?;
Some(ct[idx + BOUNDARY.len()..].to_string())
});
let body = self.take_body();
box_async! {
let body = await!(body.into_vec()).client_err()?;
let boundary = boundary.ok_or_else(|| err_fmt!("no boundary found")).client_err()?;
Ok(Multipart::with_body(Cursor::new(body), boundary))
}
}
}
pub fn form<T: serde::Serialize>(t: T) -> Response {
http::Response::builder()
.status(http::status::StatusCode::OK)
.header("Content-Type", "application/x-www-form-urlencoded")
.body(Body::from(
serde_urlencoded::to_string(&t).unwrap().into_bytes(),
))
.unwrap()
}