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;