Skip to content

Commit b1708c8

Browse files
committed
Init multipart
1 parent 82e3d5e commit b1708c8

File tree

5 files changed

+127
-1
lines changed

5 files changed

+127
-1
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ serde = { version = "1.0.106", features = ["derive"] }
4141
serde_urlencoded = "0.7.0"
4242
rand = "0.7.3"
4343
serde_qs = "0.7.0"
44+
multipart = { version = "0.16.1", default-features = false, features = ["server"], optional = true }
4445

4546
[dev-dependencies]
4647
http = "0.2.0"

src/body.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use async_std::io::{self, Cursor};
33
use serde::{de::DeserializeOwned, Serialize};
44

55
use std::fmt::{self, Debug};
6+
use std::path::PathBuf;
67
use std::pin::Pin;
78
use std::task::{Context, Poll};
89

@@ -57,6 +58,7 @@ pin_project_lite::pin_project! {
5758
reader: Box<dyn BufRead + Unpin + Send + Sync + 'static>,
5859
mime: Mime,
5960
length: Option<usize>,
61+
pub(crate) file_name: Option<PathBuf>,
6062
}
6163
}
6264

@@ -79,6 +81,7 @@ impl Body {
7981
reader: Box::new(io::empty()),
8082
mime: mime::BYTE_STREAM,
8183
length: Some(0),
84+
file_name: None,
8285
}
8386
}
8487

@@ -109,6 +112,7 @@ impl Body {
109112
reader: Box::new(reader),
110113
mime: mime::BYTE_STREAM,
111114
length: len,
115+
file_name: None,
112116
}
113117
}
114118

@@ -152,6 +156,7 @@ impl Body {
152156
mime: mime::BYTE_STREAM,
153157
length: Some(bytes.len()),
154158
reader: Box::new(io::Cursor::new(bytes)),
159+
file_name: None,
155160
}
156161
}
157162

@@ -201,6 +206,7 @@ impl Body {
201206
mime: mime::PLAIN,
202207
length: Some(s.len()),
203208
reader: Box::new(io::Cursor::new(s.into_bytes())),
209+
file_name: None,
204210
}
205211
}
206212

@@ -248,6 +254,7 @@ impl Body {
248254
length: Some(bytes.len()),
249255
reader: Box::new(Cursor::new(bytes)),
250256
mime: mime::JSON,
257+
file_name: None,
251258
};
252259
Ok(body)
253260
}
@@ -312,6 +319,7 @@ impl Body {
312319
length: Some(bytes.len()),
313320
reader: Box::new(Cursor::new(bytes)),
314321
mime: mime::FORM,
322+
file_name: None,
315323
};
316324
Ok(body)
317325
}
@@ -366,7 +374,7 @@ impl Body {
366374
P: AsRef<std::path::Path>,
367375
{
368376
let path = path.as_ref();
369-
let mut file = async_std::fs::File::open(path).await?;
377+
let mut file = async_std::fs::File::open(&path).await?;
370378
let len = file.metadata().await?.len();
371379

372380
// Look at magic bytes first, look at extension second, fall back to
@@ -380,6 +388,7 @@ impl Body {
380388
mime,
381389
length: Some(len as usize),
382390
reader: Box::new(io::BufReader::new(file)),
391+
file_name: Some(path.to_path_buf()),
383392
})
384393
}
385394

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ mod version;
139139
pub mod trace;
140140
cfg_unstable! {
141141
pub mod upgrade;
142+
pub mod multipart;
142143
}
143144

144145
pub use body::Body;

src/multipart/entry.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use crate::Body;
2+
3+
use std::fmt::{self, Debug};
4+
use std::path::PathBuf;
5+
6+
/// A single multipart entry.
7+
///
8+
/// Structurally Multipart entries are similar to `Body`.
9+
pub struct Entry {
10+
name: String,
11+
body: Body,
12+
}
13+
14+
impl Entry {
15+
/// Create a new `Entry`.
16+
pub fn new(name: impl AsRef<str>, body: impl Into<Body>) -> Self {
17+
Self {
18+
name: name.as_ref().to_owned(),
19+
body: body.into(),
20+
}
21+
}
22+
23+
/// Get the entry name.
24+
pub fn name(&self) -> &String {
25+
&self.name
26+
}
27+
28+
/// Get the file name of the entry, if it's set.
29+
pub fn file_name(&self) -> Option<&PathBuf> {
30+
self.body.file_name.as_ref()
31+
}
32+
}
33+
34+
impl Debug for Entry {
35+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36+
f.debug_struct("Entry")
37+
.field("name", &self.name)
38+
.field("body", &self.body)
39+
.finish()
40+
}
41+
}
42+
43+
// TODO
44+
// impl AsyncRead for Entry {}
45+
// impl AsRef<Body> for Entry {}
46+
// impl AsMut<Body> for Entry {}
47+
// impl Into<Body> for Entry {}

src/multipart/mod.rs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//! Multipart/form-data types.
2+
//!
3+
//! # Examples
4+
//!
5+
//! Request:
6+
//! ```
7+
//! let mut req = Request::new(Method::Get, "http://example.website");
8+
//!
9+
//! let mut multi = Multipart::new();
10+
//! multi.push("hello world");
11+
//! multi.push(Body::from_file("./cats.jpeg").await?);
12+
//!
13+
//! req.set_body(multi);
14+
//! ```
15+
//!
16+
//! Response:
17+
//!
18+
//! ```
19+
//! let mut res = Response::new(200); // get this from somewhere
20+
//!
21+
//! let mut entries = res.body_multipart();
22+
//! while let Some(entry) = entries.await {
23+
//! println!("name: {}", entry.name());
24+
//! println!("data: {}", entry.into_string()?);
25+
//! }
26+
//! ```
27+
28+
use crate::Body;
29+
pub use entry::Entry;
30+
31+
mod entry;
32+
33+
/// A multipart response body.
34+
#[derive(Debug)]
35+
pub struct Multipart {
36+
entries: Vec<Entry>,
37+
body: Option<Body>,
38+
}
39+
40+
impl Multipart {
41+
/// Create a new instance of `Multipart`.
42+
pub fn new() -> Self {
43+
Self {
44+
entries: vec![],
45+
body: None,
46+
}
47+
}
48+
49+
/// Parse a `Body` stream as a `Multipart` instance.
50+
pub fn from_body(body: Body) -> Self {
51+
Self {
52+
entries: vec![],
53+
body: Some(body),
54+
}
55+
}
56+
57+
/// Add a new entry to the `Multipart` instance.
58+
pub fn push(&mut self, name: impl AsRef<str>, body: impl Into<Body>) {
59+
let entry = Entry::new(name, body);
60+
self.entries.push(entry);
61+
}
62+
}
63+
64+
// TODO
65+
// impl Stream for Multipart {}
66+
67+
// TODO
68+
// impl From<Multipart> for Body {}

0 commit comments

Comments
 (0)