How to handle the POST request body without using a framework
Tags: dart, beginners, webdev, showdev
Published: 2018-10-10 23:09:40

---
title: How to handle the POST request body without using a framework
published: true
description: Learn how to deal with POST requests made to your server
tags: dart, beginners, webdev, showdev 
cover_image: https://thepracticaldev.s3.amazonaws.com/i/8877tv3zx5ir9tanzn5l.png
canonical_url: https://creativebracket.com/how-to-handle-the-post-request-body-without-a-framework/
---

Following the positive response from a similar [article](https://itnext.io/how-to-handle-the-post-request-body-in-node-js-without-using-a-framework-cd2038b93190) based on Node, I found it fitting that I demonstrate how this is possible in Dart. Long story short, I found it's simpler.

This example works where the `Content-Type` of the request payload is `application/x-www-form-urlencoded`, which essentially means that the form data is formatted as a query string when sent to the server.

## 1. Create our server

Create a `main.dart` file and enter the snippet below:

```dart
import 'dart:io';

void main() async {
  var server = await HttpServer.bind('localhost', 9000);

  await for (HttpRequest req in server) {
    req.response
      ..headers.set('Content-Type', 'text/html')
      ..write('''
        <!doctype html>
        <html>
        <body>
          <form action="/" method="post">
            <input type="text" name="fname" /><br />
            <input type="number" name="age" /><br />
            <input type="file" name="photo" /><br />
            <button>Save</button>
          </form>
        </body>
        </html>
      ''')
      ..close();
  }
}
```

This bootstraps our server and responds with a form when a request is made to `http://localhost:9000`. The snippet begins by importing the `dart:io` library, since it contains the classes we'll need to create our server. The whole bootstrapping process happens in a `main()` function, which is needed to run our Dart app.

To run this file, type the below command in the terminal:

```bash
dart main.dart
```

And you should be greeted with a form in the browser:

![localhost](https://thepracticaldev.s3.amazonaws.com/i/ba9z5p3rjxluez15m9se.png)

## 2. Capture the POSTed payload

Let's now ensure that we are dealing with a POST request:

```dart
...
...
await for (HttpRequest req in server) {
  if (req.method == 'POST') {
   // deal with the payload  
  } else {
    req.response
      ..headers.set('Content-Type', 'text/html')
      ..write('''
        <!doctype html>
        <html>
        <body>
          <form action="/" method="post">
            <input type="text" name="fname" /><br />
            <input type="number" name="age" /><br />
            <input type="file" name="photo" /><br />
            <button>Save</button>
          </form>
        </body>
        </html>
      ''')
      ..close();
  }
}
```

Requests to the server are treated as a `Stream`, which means that we can use the request's `transform` method to decode the content.

```dart
if (req.method == 'POST') {
  var content = await req.transform().join();
} ...
```

This won't work straightaway because the `transform` method requires a `StreamTransformer`. A `StreamTransformer` contains a `bind` method that allows it to manipulate the streaming data somehow. We need one to transform our streaming request data into a readable format, and afterwards use the `join` method to combine our _transformed_ chunks.

Beneath our `dart:io` import, let's require the `dart:convert` library:

```dart
import 'dart:io';
import 'dart:convert';
```

And use the `Utf8Decoder` as our transformer:

```dart
var content = await req.transform(Utf8Decoder()).join();
```

Printing out `content` will give you the below result, provided you filled in the form with the relevant details:

```
fname=John&age=30&photo=file.jpg
```

However, we still need to extract our key/value pairs of information from the query string. Fortunately, we have a `Uri` class in the core Dart SDK:

```dart
var content = await req.transform(Utf8Decoder()).join();
var queryParams = Uri(query: content).queryParameters;
```

## 3. Respond to the POST

Now let's send back a response:

```dart
var content = await req.transform(Utf8Decoder()).join();
var queryParams = Uri(query: content).queryParameters;

req.response
  ..write('Parsed data belonging to ${queryParams['fname']}')
  ..close();
```

**UPDATE 20/10/2018**: Tobe Osakwe(_Creator of [Angel](https://github.com/angel-dart/angel)_) helpfully pointed out the use of `splitQueryString` static method to extract the query parameters:

```dart
// var queryParams = Uri(query: content).queryParameters;
var queryParams = Uri.splitQueryString(content);
```

Our query params are returned as a `Map` object, allowing us to pull our values like this:

```dart
queryParams['fname'];
queryParams['age'];
queryParams['photo'];
```

![Solution](https://thepracticaldev.s3.amazonaws.com/i/bml5w6pdx1oj7tuyp2p7.png)

Here's the full solution:

```dart
import 'dart:io';
import 'dart:convert';

void main() async {
  var server = await HttpServer.bind('127.0.0.1', 9000);

  await for (HttpRequest req in server) {
    if (req.method == 'POST' && req.headers.contentType.toString() == 'application/x-www-form-urlencoded') {
      var content = await req.transform(Utf8Decoder()).join();
      var queryParams = Uri(query: content).queryParameters;
      req.response
        ..write('Parsed data belonging to ${queryParams['fname']}')
        ..close();
    } else {
      req.response
        ..headers.set('Content-Type', 'text/html')
        ..write('''
          <!doctype html>
          <html>
          <body>
            <form action="/" method="post">
              <input type="text" name="fname" /><br />
              <input type="number" name="age" /><br />
              <input type="file" name="photo" /><br />
              <button>Save</button>
            </form>
          </body>
          </html>
        ''')
        ..close();
    }
  }
}
```

## In closing...

Like the related article, this works for `application/x-www-form-urlencoded` content types and would require a different approach if parsing other content types. We'll look at this in a future article.

**Like, share and follow me** 😍 for more content on Dart.

---

## Further reading

1. [Hello world server in Dart](https://www.dartlang.org/tutorials/dart-vm/httpserver#run-the-hello-world-server)
2. [Creating Streams in Dart](https://www.dartlang.org/articles/libraries/creating-streams)
3. [**Free Dart Screencasts on Egghead.io**](https://egghead.io/instructors/jermaine-oppong)