use http_types::Request;
mod encoding;
mod multipart;
mod part;
mod reader_stream;
pub use encoding::Encoding;
pub use multipart::Multipart;
pub type StreamChunk = std::result::Result<Vec<u8>, futures_lite::io::Error>;
fn generate_boundary() -> String {
(0..30).map(|_| fastrand::alphanumeric()).collect()
}
pub trait RequestMultipartExt {
fn multipart(&mut self, multipart: Multipart);
}
impl RequestMultipartExt for Request {
fn multipart(&mut self, multipart: Multipart) {
multipart.set_request(self)
}
}
#[cfg(test)]
mod tests {
use crate::multipart::Multipart;
use super::*;
use http_types::{Method, Result, Url};
#[async_std::test]
async fn test_multipart_text() -> Result<()> {
let mut multipart = Multipart::new();
multipart.add_text("name", "John Doe");
multipart.add_text("age", "42");
let mut req = Request::new(Method::Post, Url::parse("http://example.com")?);
multipart.set_request(&mut req);
let content_type = req.header("Content-Type").unwrap().last().as_str();
assert!(content_type.starts_with("multipart/form-data; boundary="));
let body = req.body_string().await?;
assert!(body.contains("John Doe"));
assert!(body.contains("42"));
Ok(())
}
#[async_std::test]
async fn test_multipart_file() -> Result<()> {
let mut multipart = Multipart::new();
multipart.add_file("avatar", "Cargo.toml", None).await?;
let mut req = Request::new(Method::Post, Url::parse("http://example.com")?);
multipart.set_request(&mut req);
let content_type = req.header("Content-Type").unwrap().last().as_str();
assert!(content_type.starts_with("multipart/form-data; boundary="));
let body = req.body_string().await?;
assert!(body.contains("[package]"));
Ok(())
}
#[async_std::test]
async fn test_multipart_mixed() -> Result<()> {
let mut multipart = Multipart::new();
multipart.add_text("name", "John Doe");
multipart.add_file("avatar", "Cargo.toml", None).await?;
let mut req = Request::new(Method::Post, Url::parse("http://example.com")?);
multipart.set_request(&mut req);
let content_type = req.header("Content-Type").unwrap().last().as_str();
assert!(content_type.starts_with("multipart/form-data; boundary="));
let body = dbg!(req.body_string().await?);
assert!(body.contains("John Doe"));
assert!(body.contains("[package]"));
Ok(())
}
#[async_std::test]
async fn example_test() -> Result<()> {
use http_client::h1::H1Client as Client;
use http_client::HttpClient;
let mut multipart = Multipart::new();
multipart.add_text("name", "John Doe");
multipart.add_file("avatar", "Cargo.toml", None).await?;
let url = "https://httpbin.org/post".parse::<Url>()?;
let mut req = Request::new(Method::Post, url);
multipart.set_request(&mut req);
let client = Client::new();
let mut response = client.send(req).await?;
let body = response.body_string().await?;
println!("{}", body);
Ok(())
}
}