Выполнение HTTP-сообщения с заголовками и телом

Верно, поэтому я работал над чем-то, что требует базовой аутентификации через заголовки и передачи некоторых переменных через HTTP Post. Это терминальное приложение.

Вот как выглядит мой код:

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()));
}

Я использую httpbin в качестве эхо-сервера, поэтому он сообщает мне, что я передаю. Мой код работает правильно, если я не передаю тело или если я передаю строку в качестве тела.

Очевидно, это потому, что атрибут body в http.Request принимает только строки, и я пытаюсь передать ему карту.

Я мог бы преобразовать это в строку, и это, вероятно, сработало бы, но я все же думаю, что мой код можно улучшить. Не с точки зрения синтаксиса или того, как он справляется с будущим, но я не уверен, что использование http.dart является правильным решением.

Может ли кто-нибудь указать мне правильное направление?

Заранее спасибо.


person Marcos Placona    schedule 12.06.2014    source источник


Ответы (1)


JSON - это строка. Вам нужно закодировать свою карту в JSON и передать ее как строку.

Вы можете использовать bodyFields вместо body для передачи карты.
Таким образом, ваш content-type фиксируется на "application/x-www-form-urlencoded".

DartDoc для post говорит:

/// 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.

Некоторое время назад мне удалось отправить таким образом данные JSON.

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'));

ИЗМЕНИТЬ

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()));
}

производит

{
  "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"
}
person Günter Zöchbauer    schedule 12.06.2014
comment
Спасибо! Хотя кажется, что он не передает значения в виде формы (т.е. если вы сделаете запрос, используя упомянутый мною эхо-сервер, вы увидите форму: {} is impty - person Marcos Placona; 12.06.2014
comment
Когда вы используете bodyFields с картой или когда используете body с JSON.encoder.convert и типом содержимого 'application/json'? - person Günter Zöchbauer; 12.06.2014
comment
Если вы запустите свой пример по URL-адресу http://httpbin.org/post и выполните .then ((http.Response r) = ›Print (r.body)) вы увидите это - person Marcos Placona; 12.06.2014
comment
Я понимаю, но какую из этих двух версий вы пробовали? Оба потерпели неудачу? - person Günter Zöchbauer; 12.06.2014
comment
Фантастика! bodyfields - это то, чего мне не хватало! Теперь это работает. Большое спасибо! - person Marcos Placona; 12.06.2014
comment
@enderland Спасибо за отзыв :) - person Günter Zöchbauer; 21.04.2016
comment
как я могу отправить объект дротика через request.bodyFields ?? еще один его объект, который имеет смысл, - это body, который ожидает строку. Я не могу jsonEncode, так как он содержит сложную структуру данных. Хотя мой собственный метод toJson () обслуживает данные так же хорошо, как json, если он проверен почтальоном, но если я назначу его request.body, он говорит, что он ожидает Map ‹String, String› - person Anuran Barman; 25.09.2018
comment
Невозможно отправить сложную структуру данных по сети без ее сериализации (jsonEncode или любой другой). - person Günter Zöchbauer; 25.09.2018