Interactive Web applications typically require some type of user input (whether that user is a human,machine, or otherwise is irrelevant). Angel features built-in support for parsing request bodies with thefollowing content types:

  • application/x-www-form-urlencoded
  • application/json
  • multipart/form-data

Parsing the body

All you need to do to parse a request body is call RequestContext.parseBody. This methodis idempotent, and only ever performs the body-parsing logic once, so it is recommended to callit any time you access the request body, unless you are 100% sure that it has been parsed before.

You can access the body as a Map, List, or Object, depending on your use case:

  1. app.post('/my_form', (req, res) async {
  2. // Parse the body, if it has not already been parsed.
  3. await req.parseBody();
  4. // Access fields from the body, which is the most common use case.
  5. var userId = req.bodyAsMap['user_id'] as String;
  6. // If the user posted a List, i.e., through JSON:
  7. var count = req.bodyAsList.length;
  8. // To access the body, regardless of its runtime type:
  9. var objectBody = req.bodyAsObject as SomeType;
  10. });

Handling File Uploads

In the case of multipart/form-data, Angel will also populate the uploadedFiles field.The UploadedFile wrapper class provides mechanisms for reading content types, metadata, andaccessing the contents of an uploaded file as a Stream<List<int>>:

  1. app.post('/upload', (req, res) async {
  2. await req.parseBody();
  3. var file = req.uploadedFiles.first;
  4. if (file.contentType.type == 'video') {
  5. // Write directly to a file.
  6. await file.data.pipe(someFile.openWrite());
  7. }
  8. });

Custom Body Parsing

You can handle other content types by manually parsing the body.You can set bodyAsObject, bodyAsMap, or bodyAsList exactlyonce:

  1. Future<void> unzipPlugin(Angel app) async {
  2. app.fallback((req, res) async {
  3. if (!req.hasParsedBody
  4. && req.contentType.mimeType == 'application/zip') {
  5. var archive = await decodeZip(req.body);
  6. var fields = <String, dynamic>{};
  7. for (var file in archive.files) {
  8. fields[file.path] = file.mode;
  9. }
  10. req.bodyAsMap = fields;
  11. }
  12. return true;
  13. });
  14. }

If the user did not provide a content-type header when parseBody is called, a 400 Bad Request errorwill be thrown.