| Crates.io | http-client-multipart |
| lib.rs | http-client-multipart |
| version | 0.1.2 |
| created_at | 2025-03-19 20:07:29.335323+00 |
| updated_at | 2025-03-22 05:00:46.298313+00 |
| description | Multipart support for `http-client` |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1598551 |
| size | 103,745 |
This crate provides multipart request support for the http-client crate, enabling you to easily create and send multipart HTTP requests with file uploads and form data. It is designed to be client-agnostic, working seamlessly with any HttpClient implementation.
http-client's HttpClient trait.Content-Type header with the correct boundary.Add http-client-multipart to your Cargo.toml:
[dependencies]
http-client-multipart = "0.1.0" # Replace with the latest version
http-client = "6.5.3" # Ensure you have the base http-client crate
async-std = "1.6.0" # Or tokio, or any async runtime you prefer
Note: You also need to include a concrete implementation of the http-client's HttpClient trait (if you haven't already). Some popular choices:
http-client with h1_client (default, uses async-h1):
http-client = { version = "6.5.3", features = ["h1_client", "native-tls"] }
http-client with isahc (curl_client feature):
http-client = { version = "6.5.3", features = ["curl_client"] }
http-client with hyper (hyper_clientfeature):
http-client = { version = "6.5.3", features = ["hyper_client"] }
Here's a detailed guide on how to use the http-client-multipart crate:
use http_client::{HttpClient, Request};
use http_types::{Method, Url};
use http_client_multipart::Multipart; // Import the Multipart struct
use http_client_multipart::RequestMultipartExt; // Import the extension trait (Optional)
use async_std::task; // Or tokio, or any async runtime you prefer
Multipart instance:let mut multipart = Multipart::new();
This creates a new multipart form with a randomly generated boundary. The boundary is used to separate each part of the multipart data.
Multipart form:Use the add_text method to add standard form fields:
multipart.add_text("name", "John Doe");
multipart.add_text("age", "30");
Use the add_file (async version) method to add files from their paths on the filesystem:
multipart.add_file("avatar", "path/to/your/image.jpg").await?; // requires an async context (.await)
This automatically infers the filename and content type based on the file's path. It reads the file asynchronously, making it suitable for async contexts. The add_file function needs to be awaited as it is an async function.
If you already have file data in memory or want more control over the filename and content type, you can add file fields using add_async_read or add_sync_read.
add_async_read (Asynchronous Reader - recommended for async contexts):
use async_std::fs::File as AsyncFile;
use async_std::io::BufReader;
let file = AsyncFile::open("path/to/your/file.txt").await?;
let buf_reader = BufReader::new(file); // Wrap the async file with a buffered reader
multipart.add_async_read("document", "file.txt", "text/plain", buf_reader).await?;
This method takes an asynchronous reader (impl AsyncRead + Unpin + Send + 'static) as input, along with the desired filename and content type. The data is read asynchronously into the body. The add_async_read function needs to be awaited as it is an async function.
add_sync_read (Synchronous Reader - use with caution in async contexts):
use std::fs::File;
let file = File::open("path/to/your/file.txt")?;
multipart.add_sync_read("config", "config.txt", "text/plain", file)?;
This method takes a synchronous reader (impl Read + Seek + Send + 'static) as input, along with the desired filename and content type. Use this in synchronous contexts, or if you are very careful about thread blocking in async.
add_file_from_sync (Convenience for File objects - synchronous):
use std::fs::File;
let file = File::open("path/to/your/file.txt")?;
multipart.add_file_from_sync("archive", "data.zip", "application/zip", file)?;
This is a shorthand for creating a File object directly and adding it.
http-client Request:let url = "https://httpbin.org/post".parse::<Url>()?; // Replace with your API endpoint
let mut req = Request::new(Method::Post, url);
Multipart data as the request body:There are two ways to do this:
set_request(req: &mut Request) (Mutates Existing Request - Preferred):This is the recommended approach because it encapsulates all the logic within the Multipart struct:
multipart.set_request(&mut req)?;
This method will:
Multipart form into a Body.Content-Type header of the request to multipart/form-data with the correct boundary.RequestMultipartExt trait (Extension Method):This approach adds an extension method to the Request object:
use http_client_multipart::RequestMultipartExt;
req.set_multipart_body(multipart)?;
Both achieve the same outcome, but set_request offers better encapsulation.
HttpClient and send the request:use http_client::h1::H1Client as Client; // Example: Using h1_client
let client = Client::new();
let mut response = client.send(req).await?;
Remember to choose a concrete HttpClient implementation based on your needs (e.g., H1Client, IsahcClient, HyperClient).
let body = response.body_string().await?;
println!("{}", body);
use http_client::{HttpClient, Request};
use http_types::{Method, Url, Result};
use http_client_multipart::Multipart;
use http_client_multipart::RequestMultipartExt;
use async_std::task;
use http_client::h1::H1Client as Client;
async fn send_multipart_request() -> Result<()> {
// 1. Create a Multipart instance
let mut multipart = Multipart::new();
// 2. Add fields to the Multipart form
multipart.add_text("name", "John Doe");
multipart.add_text("age", "30");
// Add a file (assuming you have a file named "image.jpg" in the same directory)
multipart.add_file("avatar", "Cargo.toml").await?;
// 3. Create an http-client Request
let url = "https://httpbin.org/post".parse::<Url>()?; // Replace with your API endpoint
let mut req = Request::new(Method::Post, url);
// 4. Set the Multipart data as the request body using set_request()
multipart.set_request(&mut req)?;
// 5. Create an HttpClient and send the request
let client = Client::new(); // Or any other HttpClient implementation
let mut response = client.send(req).await?;
// 6. Handle the response
let body = response.body_string().await?;
println!("{}", body);
Ok(())
}
fn main() -> Result<()> {
task::block_on(async {
send_multipart_request().await
})
}
? for error propagation. In a real application, handle errors gracefully.add_file are correct and accessible.add_async_read or add_sync_read if the automatic detection is inaccurate.add_async_read.This crate is licensed under the MIT License.