formData method

Future<Map<String, Object?>> formData()

Implementation

Future<Map<String, Object?>> formData() async {
  final contentType = headers.get('content-type');
  if (contentType == null) return {};

  final mediaType = MediaType.parse(contentType);
  if (mediaType.mimeType == 'application/x-www-form-urlencoded') {
    final text = await body.text();
    return Uri.splitQueryString(text);
  }

  if (mediaType.mimeType == 'multipart/form-data') {
    final boundary = mediaType.parameters['boundary'];
    if (boundary == null) return {};

    final transformer = MimeMultipartTransformer(boundary);
    final parts = body.stream.transform(transformer);

    final data = <String, Object?>{};

    await for (final part in parts) {
      final contentDisposition = part.headers['content-disposition'];
      if (contentDisposition != null) {
        final header = _HeaderValue.parse(contentDisposition);
        final name = header.parameters['name'];
        final filename = header.parameters['filename'];

        if (name != null) {
          if (filename != null) {
            // It's a file
            final bytes =
                await part.fold<List<int>>([], (p, e) => p..addAll(e));
            data[name] = MultipartFile(
              filename: filename,
              contentType: part.headers['content-type'],
              bytes: bytes,
            );
          } else if (part.headers['content-type'] == dvFlatContentType) {
            // A field packed as a binary flat buffer, which is what the
            // transport spec asks for: over text multipart every value
            // arrives as a String and the type is gone by the time a
            // parameter is decoded.
            //
            // A damaged buffer is refused rather than falling back to text.
            // Handing a parameter the raw bytes of a corrupt envelope is
            // exactly the plausible-looking wrong value this is meant to
            // prevent.
            final bytes =
                await part.fold<List<int>>(<int>[], (p, e) => p..addAll(e));
            data[name] = dvFlatDecode(Uint8List.fromList(bytes));
          } else {
            // It's a field
            final value = await utf8.decodeStream(part);
            data[name] = value;
          }
        }
      }
    }
    return data;
  }

  return {};
}