slack_morphism/
multipart_form.rs

1use crate::AnyStdResult;
2use bytes::{BufMut, Bytes, BytesMut};
3use std::fmt::Write;
4
5pub struct FileMultipartData<'a> {
6    pub name: String,
7    pub content_type: String,
8    pub data: &'a [u8],
9}
10
11#[cfg(feature = "hyper")]
12pub fn generate_multipart_boundary() -> String {
13    format!(
14        "----WebKitFormBoundarySlackMorphismRust{}",
15        chrono::Utc::now().timestamp()
16    )
17}
18
19#[cfg(feature = "hyper")]
20pub fn create_multipart_file_content<'p, PT, TS>(
21    fields: &'p PT,
22    multipart_boundary: &str,
23    file: Option<FileMultipartData<'p>>,
24) -> AnyStdResult<Bytes>
25where
26    PT: std::iter::IntoIterator<Item = (&'p str, Option<TS>)> + Clone,
27    TS: AsRef<str> + 'p + Send,
28{
29    let capacity = file.as_ref().map(|x| x.data.len()).unwrap_or(0) + 1024;
30    let mut output = BytesMut::with_capacity(capacity);
31    output.write_str("\r\n")?;
32
33    if let Some(file_to_upload) = file {
34        output.write_str("\r\n")?;
35        output.write_str("--")?;
36        output.write_str(multipart_boundary)?;
37        output.write_str("\r\n")?;
38        output.write_str(&format!(
39            "Content-Disposition: form-data; name=\"file\"; filename=\"{}\"",
40            file_to_upload.name
41        ))?;
42        output.write_str("\r\n")?;
43        output.write_str(&format!("Content-Type: {}", file_to_upload.content_type))?;
44        output.write_str("\r\n")?;
45        output.write_str(&format!("Content-Length: {}", file_to_upload.data.len()))?;
46        output.write_str("\r\n")?;
47        output.write_str("\r\n")?;
48        output.put_slice(file_to_upload.data);
49    }
50
51    for (k, mv) in fields.clone().into_iter() {
52        if let Some(v) = mv {
53            let vs = v.as_ref();
54            output.write_str("\r\n")?;
55            output.write_str("--")?;
56            output.write_str(multipart_boundary)?;
57            output.write_str("\r\n")?;
58            output.write_str(&format!("Content-Disposition: form-data; name=\"{}\"", k))?;
59            output.write_str("\r\n")?;
60            output.write_str(&format!("Content-Length: {}", vs.len()))?;
61            output.write_str("\r\n")?;
62            output.write_str("\r\n")?;
63            output.write_str(vs)?;
64        }
65    }
66
67    output.write_str("\r\n")?;
68    output.write_str("--")?;
69    output.write_str(multipart_boundary)?;
70
71    Ok(output.freeze())
72}