mpart_async/
lib.rs

1#![deny(missing_docs)]
2//! # Rust Multipart Async
3//!
4//! This crate allows the creation of client/server `multipart/form-data` streams for use with std futures & async
5//! ## Quick Usage
6//!
7//! With clients, you want to create a [`MultipartRequest`](client/struct.MultipartRequest.html) & add in your fields & files.
8//!
9//! With server, you want to use a [`MultipartStream`](server/struct.MultipartStream.html) to retrieve a stream of streams.
10//!
11//! You can also use the lower level [`MultipartParser`](server/struct.MultipartParser.html) to retrieve a stream emitting either Headers or Byte Chunks
12//!
13//! ### Hyper Client Example
14//!
15//! Here is an example of how to use the client with hyper:
16//!
17//! ```no_run
18//! use hyper::{header::CONTENT_TYPE, Body, Client, Request};
19//! use hyper::{service::make_service_fn, service::service_fn, Response, Server};
20//! use mpart_async::client::MultipartRequest;
21//!
22//! type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
23//!
24//! #[tokio::main]
25//! async fn main() -> Result<(), Error> {
26//!     //Setup a mock server to accept connections.
27//!     setup_server();
28//!
29//!     let client = Client::new();
30//!
31//!     let mut mpart = MultipartRequest::default();
32//!
33//!     mpart.add_field("foo", "bar");
34//!     mpart.add_file("test", "Cargo.toml");
35//!
36//!     let request = Request::post("http://localhost:3000")
37//!         .header(
38//!             CONTENT_TYPE,
39//!             format!("multipart/form-data; boundary={}", mpart.get_boundary()),
40//!         )
41//!         .body(Body::wrap_stream(mpart))?;
42//!
43//!     client.request(request).await?;
44//!
45//!     Ok(())
46//! }
47//!
48//! fn setup_server() {
49//!     let addr = ([127, 0, 0, 1], 3000).into();
50//!     let make_svc = make_service_fn(|_conn| async { Ok::<_, Error>(service_fn(mock)) });
51//!     let server = Server::bind(&addr).serve(make_svc);
52//!
53//!     tokio::spawn(server);
54//! }
55//!
56//! async fn mock(_: Request<Body>) -> Result<Response<Body>, Error> {
57//!     Ok(Response::new(Body::from("")))
58//! }
59//! ```
60//!
61//! ### Warp Server Example
62//!
63//! Here is an example of using it with the warp server:
64//!
65//! ```no_run
66//! use warp::Filter;
67//!
68//! use bytes::Buf;
69//! use futures_util::TryStreamExt;
70//! use futures_core::Stream;
71//! use mime::Mime;
72//! use mpart_async::server::MultipartStream;
73//! use std::convert::Infallible;
74//!
75//! #[tokio::main]
76//! async fn main() {
77//!     // Match any request and return hello world!
78//!     let routes = warp::any()
79//!         .and(warp::header::<Mime>("content-type"))
80//!         .and(warp::body::stream())
81//!         .and_then(mpart);
82//!
83//!     warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
84//! }
85//!
86//! async fn mpart(
87//!     mime: Mime,
88//!     body: impl Stream<Item = Result<impl Buf, warp::Error>> + Unpin,
89//! ) -> Result<impl warp::Reply, Infallible> {
90//!     let boundary = mime.get_param("boundary").map(|v| v.to_string()).unwrap();
91//!
92//!     let mut stream = MultipartStream::new(
93//!         boundary,
94//!         body.map_ok(|mut buf| buf.copy_to_bytes(buf.remaining())),
95//!     );
96//!
97//!     while let Ok(Some(mut field)) = stream.try_next().await {
98//!         println!("Field received:{}", field.name().unwrap());
99//!         if let Ok(filename) = field.filename() {
100//!             println!("Field filename:{}", filename);
101//!         }
102//!
103//!         while let Ok(Some(bytes)) = field.try_next().await {
104//!             println!("Bytes received:{}", bytes.len());
105//!         }
106//!     }
107//!
108//!     Ok(format!("Thanks!\n"))
109//! }
110//! ```
111
112/// The Client Module used for sending requests to servers
113///
114pub mod client;
115/// Server structs for use when parsing requests from clients
116pub mod server;
117
118/// The FileStream is a tokio way of streaming out a file from a given path.
119///
120/// This allows you to do `FileStream::new("/path/to/file")` to create a stream of Bytes of the file
121#[cfg(feature = "filestream")]
122pub mod filestream;