Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doing an HTTP Post with headers and a body

Tags:

dart

dart-io

Right, so I've been working on something which requires basic authentication through headers, and passing some variables via HTTP Post. This is a terminal app.

This is what my code looks like:

import 'package:http/http.dart' as http;
import 'dart:io';
void main() {
  var url = "http://httpbin.org/post";
  var client = new http.Client();
  var request = new http.Request('POST', Uri.parse(url));
  var body = {'content':'this is a test', 'email':'[email protected]', 'number':'441276300056'};
  request.headers[HttpHeaders.CONTENT_TYPE] = 'application/json; charset=utf-8';
  request.headers[HttpHeaders.AUTHORIZATION] = 'Basic 021215421fbe4b0d27f:e74b71bbce';
  request.body = body;
  var future = client.send(request).then((response) => response.stream.bytesToString().then((value) => print(value.toString()))).catchError((error) => print(error.toString()));
}

I'm using httpbin as an echo server, so it tells me what I'm passing in. My code works correctly if I don't pass a body, or if I pass a string as the body.

Obviously that's because the body attribute in http.Request only accepts strings, and I'm trying to pass a map to it.

I could convert that to a string, and it would probably work, but I still think my code could be improved. Not from a syntax point of view, or from how it's handling the future, but I'm not certain using http.dart is the right thing to do.

Could someone point me in the right direction?

Thanks in advance.

like image 575
Marcos Placona Avatar asked Jun 12 '14 11:06

Marcos Placona


1 Answers

JSON is a String. You need to encode your map to JSON and pass it as a String.

You can use bodyFields instead of body to pass a Map.
This way your content-type is fixed to "application/x-www-form-urlencoded".

The DartDoc for post says:

/// If [body] is a Map, it's encoded as form fields using [encoding]. The
/// content-type of the request will be set to
/// `"application/x-www-form-urlencoded"`; this cannot be overridden.

I was able to send JSON data this way a while ago

return new http.Client()
  .post(url, headers: {'Content-type': 'application/json'},
      body: JSON.encoder.convert({"distinct": "users","key": "account","query": {"active":true}}))
      .then((http.Response r) => r.body)
      .whenComplete(() => print('completed'));

EDIT

import 'package:http/http.dart' as http;
import 'dart:io';
void main() {
  var url = "http://httpbin.org/post";
  var client = new http.Client();
  var request = new http.Request('POST', Uri.parse(url));
  var body = {'content':'this is a test', 'email':'[email protected]', 'number':'441276300056'};
//  request.headers[HttpHeaders.CONTENT_TYPE] = 'application/json; charset=utf-8';
  request.headers[HttpHeaders.AUTHORIZATION] = 'Basic 021215421fbe4b0d27f:e74b71bbce';
  request.bodyFields = body;
  var future = client.send(request).then((response)
      => response.stream.bytesToString().then((value)
          => print(value.toString()))).catchError((error) => print(error.toString()));
}

produces

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "content": "this is a test", 
    "email": "[email protected]", 
    "number": "441276300056"
  }, 
  "headers": {
    "Accept-Encoding": "gzip", 
    "Authorization": "Basic 021215421fbe4b0d27f:e74b71bbce", 
    "Connection": "close", 
    "Content-Length": "63", 
    "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", 
    "Host": "httpbin.org", 
    "User-Agent": "Dart/1.5 (dart:io)", 
    "X-Request-Id": "b108713b-d746-49de-b9c2-61823a93f629"
  }, 
  "json": null, 
  "origin": "91.118.62.43", 
  "url": "http://httpbin.org/post"
}
like image 92
Günter Zöchbauer Avatar answered Sep 28 '22 13:09

Günter Zöchbauer