Skip to content

Commit e97e28d

Browse files
committed
docs(multipart): improve crate root docs
1 parent 16125bd commit e97e28d

File tree

6 files changed

+131
-106
lines changed

6 files changed

+131
-106
lines changed

actix-multipart/Cargo.toml

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ version = "0.7.2"
44
authors = [
55
"Nikolay Kim <[email protected]>",
66
"Jacob Halsey <[email protected]>",
7+
"Rob Ede <[email protected]>",
78
]
8-
description = "Multipart form support for Actix Web"
9-
keywords = ["http", "web", "framework", "async", "futures"]
10-
homepage = "https://actix.rs"
11-
repository = "https://github.com/actix/actix-web"
12-
license = "MIT OR Apache-2.0"
13-
edition = "2021"
9+
description = "Multipart request & form support for Actix Web"
10+
keywords = ["http", "actix", "web", "multipart", "form"]
11+
homepage.workspace = true
12+
repository.workspace = true
13+
license.workspace = true
14+
edition.workspace = true
1415

1516
[package.metadata.docs.rs]
1617
rustdoc-args = ["--cfg", "docsrs"]

actix-multipart/README.md

+9-3
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@
1515

1616
<!-- cargo-rdme start -->
1717

18-
Multipart form support for Actix Web.
18+
Multipart request & form support for Actix Web.
19+
20+
The [`Multipart`] extractor aims to support all kinds of `multipart/*` requests, including `multipart/form-data`, `multipart/related` and `multipart/mixed`. This is a lower-level extractor which supports reading [multipart fields](Field), in the order they are sent by the client.
21+
22+
Due to additional requirements for `multipart/form-data` requests, the higher level [`MultipartForm`] extractor and derive macro only supports this media type.
1923

2024
## Examples
2125

2226
```rust
2327
use actix_web::{post, App, HttpServer, Responder};
2428

25-
use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm};
29+
use actix_multipart::form::{json::Json as MpJson, tempfile::TempFile, MultipartForm};
2630
use serde::Deserialize;
2731

2832
#[derive(Debug, Deserialize)]
@@ -34,7 +38,7 @@ struct Metadata {
3438
struct UploadForm {
3539
#[multipart(limit = "100MB")]
3640
file: TempFile,
37-
json: MPJson<Metadata>,
41+
json: MpJson<Metadata>,
3842
}
3943

4044
#[post("/videos")]
@@ -63,6 +67,8 @@ curl -v --request POST \
6367
-F file=@./Cargo.lock
6468
```
6569

70+
[`MultipartForm`]: struct@form::MultipartForm
71+
6672
<!-- cargo-rdme end -->
6773

6874
[More available in the examples repo &rarr;](https://github.com/actix/examples/tree/master/forms/multipart)

actix-multipart/src/form/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Process and extract typed data from a multipart stream.
1+
//! Extract and process typed data from fields of a `multipart/form-data` request.
22
33
use std::{
44
any::Any,

actix-multipart/src/lib.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
//! Multipart form support for Actix Web.
1+
//! Multipart request & form support for Actix Web.
2+
//!
3+
//! The [`Multipart`] extractor aims to support all kinds of `multipart/*` requests, including
4+
//! `multipart/form-data`, `multipart/related` and `multipart/mixed`. This is a lower-level
5+
//! extractor which supports reading [multipart fields](Field), in the order they are sent by the
6+
//! client.
7+
//!
8+
//! Due to additional requirements for `multipart/form-data` requests, the higher level
9+
//! [`MultipartForm`] extractor and derive macro only supports this media type.
210
//!
311
//! # Examples
412
//!
@@ -45,6 +53,8 @@
4553
//! -F 'json={"name": "Cargo.lock"};type=application/json' \
4654
//! -F file=@./Cargo.lock
4755
//! ```
56+
//!
57+
//! [`MultipartForm`]: struct@form::MultipartForm
4858
4959
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
5060
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]

actix-multipart/src/multipart.rs

+1-95
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ mod tests {
483483
};
484484
use assert_matches::assert_matches;
485485
use futures_test::stream::StreamTestExt as _;
486-
use futures_util::{future::lazy, stream, StreamExt as _};
486+
use futures_util::{stream, StreamExt as _};
487487
use tokio::sync::mpsc;
488488
use tokio_stream::wrappers::UnboundedReceiverStream;
489489

@@ -718,100 +718,6 @@ mod tests {
718718
}
719719
}
720720

721-
#[actix_rt::test]
722-
async fn test_basic() {
723-
let (_, payload) = h1::Payload::create(false);
724-
let mut payload = PayloadBuffer::new(payload);
725-
726-
assert_eq!(payload.buf.len(), 0);
727-
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
728-
assert_eq!(None, payload.read_max(1).unwrap());
729-
}
730-
731-
#[actix_rt::test]
732-
async fn test_eof() {
733-
let (mut sender, payload) = h1::Payload::create(false);
734-
let mut payload = PayloadBuffer::new(payload);
735-
736-
assert_eq!(None, payload.read_max(4).unwrap());
737-
sender.feed_data(Bytes::from("data"));
738-
sender.feed_eof();
739-
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
740-
741-
assert_eq!(Some(Bytes::from("data")), payload.read_max(4).unwrap());
742-
assert_eq!(payload.buf.len(), 0);
743-
assert!(payload.read_max(1).is_err());
744-
assert!(payload.eof);
745-
}
746-
747-
#[actix_rt::test]
748-
async fn test_err() {
749-
let (mut sender, payload) = h1::Payload::create(false);
750-
let mut payload = PayloadBuffer::new(payload);
751-
assert_eq!(None, payload.read_max(1).unwrap());
752-
sender.set_error(PayloadError::Incomplete(None));
753-
lazy(|cx| payload.poll_stream(cx)).await.err().unwrap();
754-
}
755-
756-
#[actix_rt::test]
757-
async fn read_max() {
758-
let (mut sender, payload) = h1::Payload::create(false);
759-
let mut payload = PayloadBuffer::new(payload);
760-
761-
sender.feed_data(Bytes::from("line1"));
762-
sender.feed_data(Bytes::from("line2"));
763-
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
764-
assert_eq!(payload.buf.len(), 10);
765-
766-
assert_eq!(Some(Bytes::from("line1")), payload.read_max(5).unwrap());
767-
assert_eq!(payload.buf.len(), 5);
768-
769-
assert_eq!(Some(Bytes::from("line2")), payload.read_max(5).unwrap());
770-
assert_eq!(payload.buf.len(), 0);
771-
}
772-
773-
#[actix_rt::test]
774-
async fn read_exactly() {
775-
let (mut sender, payload) = h1::Payload::create(false);
776-
let mut payload = PayloadBuffer::new(payload);
777-
778-
assert_eq!(None, payload.read_exact(2));
779-
780-
sender.feed_data(Bytes::from("line1"));
781-
sender.feed_data(Bytes::from("line2"));
782-
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
783-
784-
assert_eq!(Some(Bytes::from_static(b"li")), payload.read_exact(2));
785-
assert_eq!(payload.buf.len(), 8);
786-
787-
assert_eq!(Some(Bytes::from_static(b"ne1l")), payload.read_exact(4));
788-
assert_eq!(payload.buf.len(), 4);
789-
}
790-
791-
#[actix_rt::test]
792-
async fn read_until() {
793-
let (mut sender, payload) = h1::Payload::create(false);
794-
let mut payload = PayloadBuffer::new(payload);
795-
796-
assert_eq!(None, payload.read_until(b"ne").unwrap());
797-
798-
sender.feed_data(Bytes::from("line1"));
799-
sender.feed_data(Bytes::from("line2"));
800-
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
801-
802-
assert_eq!(
803-
Some(Bytes::from("line")),
804-
payload.read_until(b"ne").unwrap()
805-
);
806-
assert_eq!(payload.buf.len(), 6);
807-
808-
assert_eq!(
809-
Some(Bytes::from("1line2")),
810-
payload.read_until(b"2").unwrap()
811-
);
812-
assert_eq!(payload.buf.len(), 0);
813-
}
814-
815721
#[actix_rt::test]
816722
async fn test_multipart_from_error() {
817723
let err = Error::ContentTypeMissing;

actix-multipart/src/payload.rs

+102
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,105 @@ impl PayloadBuffer {
151151
self.buf.extend_from_slice(&buf);
152152
}
153153
}
154+
155+
#[cfg(test)]
156+
mod tests {
157+
use actix_http::h1;
158+
use futures_util::future::lazy;
159+
160+
use super::*;
161+
162+
#[actix_rt::test]
163+
async fn basic() {
164+
let (_, payload) = h1::Payload::create(false);
165+
let mut payload = PayloadBuffer::new(payload);
166+
167+
assert_eq!(payload.buf.len(), 0);
168+
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
169+
assert_eq!(None, payload.read_max(1).unwrap());
170+
}
171+
172+
#[actix_rt::test]
173+
async fn eof() {
174+
let (mut sender, payload) = h1::Payload::create(false);
175+
let mut payload = PayloadBuffer::new(payload);
176+
177+
assert_eq!(None, payload.read_max(4).unwrap());
178+
sender.feed_data(Bytes::from("data"));
179+
sender.feed_eof();
180+
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
181+
182+
assert_eq!(Some(Bytes::from("data")), payload.read_max(4).unwrap());
183+
assert_eq!(payload.buf.len(), 0);
184+
assert!(payload.read_max(1).is_err());
185+
assert!(payload.eof);
186+
}
187+
188+
#[actix_rt::test]
189+
async fn err() {
190+
let (mut sender, payload) = h1::Payload::create(false);
191+
let mut payload = PayloadBuffer::new(payload);
192+
assert_eq!(None, payload.read_max(1).unwrap());
193+
sender.set_error(PayloadError::Incomplete(None));
194+
lazy(|cx| payload.poll_stream(cx)).await.err().unwrap();
195+
}
196+
197+
#[actix_rt::test]
198+
async fn read_max() {
199+
let (mut sender, payload) = h1::Payload::create(false);
200+
let mut payload = PayloadBuffer::new(payload);
201+
202+
sender.feed_data(Bytes::from("line1"));
203+
sender.feed_data(Bytes::from("line2"));
204+
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
205+
assert_eq!(payload.buf.len(), 10);
206+
207+
assert_eq!(Some(Bytes::from("line1")), payload.read_max(5).unwrap());
208+
assert_eq!(payload.buf.len(), 5);
209+
210+
assert_eq!(Some(Bytes::from("line2")), payload.read_max(5).unwrap());
211+
assert_eq!(payload.buf.len(), 0);
212+
}
213+
214+
#[actix_rt::test]
215+
async fn read_exactly() {
216+
let (mut sender, payload) = h1::Payload::create(false);
217+
let mut payload = PayloadBuffer::new(payload);
218+
219+
assert_eq!(None, payload.read_exact(2));
220+
221+
sender.feed_data(Bytes::from("line1"));
222+
sender.feed_data(Bytes::from("line2"));
223+
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
224+
225+
assert_eq!(Some(Bytes::from_static(b"li")), payload.read_exact(2));
226+
assert_eq!(payload.buf.len(), 8);
227+
228+
assert_eq!(Some(Bytes::from_static(b"ne1l")), payload.read_exact(4));
229+
assert_eq!(payload.buf.len(), 4);
230+
}
231+
232+
#[actix_rt::test]
233+
async fn read_until() {
234+
let (mut sender, payload) = h1::Payload::create(false);
235+
let mut payload = PayloadBuffer::new(payload);
236+
237+
assert_eq!(None, payload.read_until(b"ne").unwrap());
238+
239+
sender.feed_data(Bytes::from("line1"));
240+
sender.feed_data(Bytes::from("line2"));
241+
lazy(|cx| payload.poll_stream(cx)).await.unwrap();
242+
243+
assert_eq!(
244+
Some(Bytes::from("line")),
245+
payload.read_until(b"ne").unwrap()
246+
);
247+
assert_eq!(payload.buf.len(), 6);
248+
249+
assert_eq!(
250+
Some(Bytes::from("1line2")),
251+
payload.read_until(b"2").unwrap()
252+
);
253+
assert_eq!(payload.buf.len(), 0);
254+
}
255+
}

0 commit comments

Comments
 (0)