///|
pub(all) struct MultipartBody {
content_type : String
body : Bytes
} derive(Eq, Debug)
///|
/// Build a deterministic multipart/form-data body without filesystem or clock
/// access, keeping media upload available on every target.
pub fn multipart_file(
boundary : String,
field_name : String,
file_name : String,
mime_type : String,
bytes : Bytes,
fields? : Array[(String, String)] = [],
) -> MultipartBody raise MegalodonError {
if boundary == "" || boundary.contains("\r") || boundary.contains("\n") {
raise InvalidRequest("invalid multipart boundary")
}
let out = @buffer.Buffer()
for entry in fields {
let (name, value) = entry
out.write_string_utf8("--\{boundary}\r\n")
out.write_string_utf8(
"Content-Disposition: form-data; name=\"\{name}\"\r\n\r\n",
)
out.write_string_utf8(value)
out.write_string_utf8("\r\n")
}
out.write_string_utf8("--\{boundary}\r\n")
out.write_string_utf8(
"Content-Disposition: form-data; name=\"\{field_name}\"; filename=\"\{file_name}\"\r\n",
)
out.write_string_utf8("Content-Type: \{mime_type}\r\n\r\n")
out.write_bytes(bytes[:])
out.write_string_utf8("\r\n--\{boundary}--\r\n")
{
content_type: "multipart/form-data; boundary=\{boundary}",
body: out.to_bytes(),
}
}