formfields.rs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // -*- coding: utf-8 -*-
  2. //
  3. // Simple CMS
  4. //
  5. // Copyright (C) 2011-2024 Michael Büsch <m@bues.ch>
  6. //
  7. // Licensed under the Apache License version 2.0
  8. // or the MIT license, at your option.
  9. // SPDX-License-Identifier: Apache-2.0 OR MIT
  10. use anyhow::{self as ah, Context as _};
  11. use multer::{parse_boundary, Constraints, Multipart, SizeLimit};
  12. use std::collections::HashMap;
  13. const LIMIT_WHOLE_STREAM: u64 = 1024 * 1024;
  14. const LIMIT_PER_FIELD: u64 = 1024 * 128;
  15. pub struct FormFields {
  16. items: HashMap<String, Vec<u8>>,
  17. }
  18. impl FormFields {
  19. pub async fn new(body: &[u8], body_mime: &str) -> ah::Result<Self> {
  20. let boundary = parse_boundary(body_mime).context("Parse form-data boundary")?;
  21. let sizelim = SizeLimit::new()
  22. .whole_stream(LIMIT_WHOLE_STREAM)
  23. .per_field(LIMIT_PER_FIELD);
  24. let constr = Constraints::new().size_limit(sizelim);
  25. let mut multipart = Multipart::with_reader_with_constraints(body, boundary, constr);
  26. let mut items = HashMap::new();
  27. while let Some(field) = multipart.next_field().await.context("Multipart field")? {
  28. let Some(name) = field.name() else {
  29. continue;
  30. };
  31. let name = name.to_string();
  32. let Ok(data) = field.bytes().await else {
  33. continue;
  34. };
  35. let data = data.to_vec();
  36. items.insert(name, data);
  37. }
  38. Ok(Self { items })
  39. }
  40. pub fn into_items(self) -> HashMap<String, Vec<u8>> {
  41. self.items
  42. }
  43. }
  44. // vim: ts=4 sw=4 expandtab