HTTP POST с Json on Body - Flutter/Dart

Это мой код для запроса API:

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

Future<http.Response> postRequest () async {
  var url ='https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  var body = jsonEncode({ 'data': { 'apikey': '12345678901234567890' } });

  print("Body: " + body);

  http.post(url,
      headers: {"Content-Type": "application/json"},
      body: body
  ).then((http.Response response) {
    print("Response status: ${response.statusCode}");
    print("Response body: ${response.contentLength}");
    print(response.headers);
    print(response.request);

  });
  }

У меня проблема с ответом на запрос, в котором предполагается, что тело имеет json, но что-то пошло не так, и я думаю, что с json, который я отправляю по запросу body, потому что это вложенный объект json, и значение ключа является объектом json. Я хотел бы знать, как я могу разобрать JSON правильно и вставить в тело запроса.

это заголовок ответа:

 {set-cookie: JSESSIONID=DA65FBCBA2796D173F8C8D78AD87F9AD;path=/testes2/;HttpOnly, last-modified: Thu, 10 May 2018 17:15:13 GMT, cache-control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0, date: Thu, 10 May 2018 17:15:13 GMT, content-length: 0, pragma: no-cache, content-type: text/html, server: Apache-Coyote/1.1, expires: Tue, 03 Jul 2001 06:00:00 GMT}

и вот как это должно быть:

Server: Apache-Coyote/1.1
Expires: Tue, 03 Jul 2001 06:00:00 GMT
Last-Modified: Thu, 10 May 2018 17:17:07 GMT
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Vary: Accept-Encoding
Set-Cookie: JSESSIONID=84813CC68E0E8EA6021CB0B4C2F245BC;path=/testes2/;HttpOnly
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked

ответ body пуст, и я думаю, что это потому, что тело, которое я отправил по запросу, может ли кто-нибудь помочь мне с вложенным объектом json в значении??

СКРИНШОТ ПОЧТЫ:

Ответы

Ответ 1

ОК, наконец, у нас есть ответ...

Вы правильно указываете headers: {"Content-Type": "application/json"}, чтобы установить тип содержимого. Под капотом либо пакет http либо нижний уровень dart:io HttpClient меняет это на application/json; charset=utf-8 application/json; charset=utf-8. Тем не менее, ваше веб-приложение на сервере, очевидно, не ожидает суффикса.

Чтобы доказать это, я попробовал это на Java, с двумя версиями

conn.setRequestProperty("content-type", "application/json; charset=utf-8"); // fails
conn.setRequestProperty("content-type", "application/json"); // works

Можете ли вы связаться с владельцем веб-приложения, чтобы объяснить их ошибку? Я не вижу, где Дарт добавляет суффикс, но я посмотрю позже.

EDIT. Позже исследование показывает, что это пакет http, который, выполняя много усилий для вас, добавляет суффикс, который не нравится вашему серверу. Если вы не можете заставить их исправить сервер, вы можете обойти http и напрямую использовать dart:io HttpClient. В итоге вы получаете немного шаблона, который обычно обрабатывается для вас по http.

Ниже приведен рабочий пример:

import 'dart:convert';
import 'dart:io';
import 'dart:async';

main() async {
  String url =
      'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  Map map = {
    'data': {'apikey': '12345678901234567890'},
  };

  print(await apiRequest(url, map));
}

Future<String> apiRequest(String url, Map jsonMap) async {
  HttpClient httpClient = new HttpClient();
  HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
  request.headers.set('content-type', 'application/json');
  request.add(utf8.encode(json.encode(jsonMap)));
  HttpClientResponse response = await request.close();
  // todo - you should check the response.statusCode
  String reply = await response.transform(utf8.decoder).join();
  httpClient.close();
  return reply;
}

В зависимости от вашего варианта использования может быть более эффективным повторное использование HttpClient, вместо того, чтобы создавать новый для каждого запроса. Todo - добавьте обработку ошибок ;-)

Ответ 2

Это работает!

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

Future<http.Response> postRequest () async {
  var url ='https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';

  Map data = {
    'apikey': '12345678901234567890'
  }
  //encode Map to JSON
  var body = json.encode(data);

  var response = await http.post(url,
      headers: {"Content-Type": "application/json"},
      body: body
  );
  print("${response.statusCode}");
  print("${response.body}");
  return response;
}

Ответ 3

Это также будет работать:

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

  sendRequest() async {

    Map data = {
       'apikey': '12345678901234567890'
    };

    var url = 'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
    http.post(url, body: data)
        .then((response) {
      print("Response status: ${response.statusCode}");
      print("Response body: ${response.body}");
    });  
  }

Ответ 4

Этот для использования класса HTTPClient

 request.headers.add("body", json.encode(map));

Я прикрепил закодированные данные тела json к заголовку и добавил к нему. Меня устраивает.