How to make HTTP POST request with url encoded body in flutter?

I came here just trying to make an HTTP POST request. Here is an example of how to do that:

import 'dart:convert';
import 'package:http/http.dart';


makePostRequest() async {

  final uri = Uri.parse('http://httpbin.org/post');
  final headers = {'Content-Type': 'application/json'};
  Map<String, dynamic> body = {'id': 21, 'name': 'bob'};
  String jsonBody = json.encode(body);
  final encoding = Encoding.getByName('utf-8');

  Response response = await post(
    uri,
    headers: headers,
    body: jsonBody,
    encoding: encoding,
  );

  int statusCode = response.statusCode;
  String responseBody = response.body;
}

See also

  • How to make HTTP requests in Flutter

I'd like to recommend dio package to you , dio is a powerful Http client for Dart/Flutter, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc.

dio is very easy to use, in your case you can:

Map<String, String> body = {
'name': 'doodle',
'color': 'blue',
'teamJson': {
  'homeTeam': {'team': 'Team A'},
  'awayTeam': {'team': 'Team B'},
  },
};

dio.post("/info",data:body, options: 
  new Options(contentType:ContentType.parse("application/x-www-form-urlencoded")))    

dio can encode the data automatically.

More details please refer to dio.


You need to add three additional steps: First, you need to convert the JSON map to a String (using json.encode) Then you need to Uri encode it if you want to send it as application/x-www-form-urlencoded. Lastly, you need to give the parameter that you are posting a name.

For example (note, this is using the dart:io HttpClient, but it's basically the same):

  Future<HttpClientResponse> foo() async {
    Map<String, dynamic> jsonMap = {
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    };
    String jsonString = json.encode(jsonMap); // encode map to json
    String paramName = 'param'; // give the post param a name
    String formBody = paramName + '=' + Uri.encodeQueryComponent(jsonString);
    List<int> bodyBytes = utf8.encode(formBody); // utf8 encode
    HttpClientRequest request =
        await _httpClient.post(_host, _port, '/a/b/c');
    // it's polite to send the body length to the server
    request.headers.set('Content-Length', bodyBytes.length.toString());
    // todo add other headers here
    request.add(bodyBytes);
    return await request.close();
  }

The above is for the dart:io version (which, of course, you can use in Flutter) If you would like to stick with the package:http version, then you need to tweak your Map a bit. body must be a Map<String, String>. You need to decide what you want as your POST parameters. Do you want two: homeTeam and awayTeam? or one, say, teamJson?

This code

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'homeTeam': json.encode(
      {'team': 'Team A'},
    ),
    'awayTeam': json.encode(
      {'team': 'Team B'},
    ),
  };

  Response r = await post(
    url,
    body: body,
  );

produces this on the wire

name=doodle&color=blue&homeTeam=%7B%22team%22%3A%22Team+A%22%7D&awayTeam=%7B%22team%22%3A%22Team+B%22%7D

alternatively, this

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'teamJson': json.encode({
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    }),
  };

  Response r = await post(
    url,
    body: body,
  );

produces this on the wire

name=doodle&color=blue&teamJson=%7B%22homeTeam%22%3A%7B%22team%22%3A%22Team+A%22%7D%2C%22awayTeam%22%3A%7B%22team%22%3A%22Team+B%22%7D%7D

the package:http client takes care of: encoding the Uri.encodeQueryComponent, utf8 encoding (note that that's the default, so no need to specify it) and sending the length in the Content-Length header. You must still do the json encoding.

Tags:

Dart

Flutter