Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTP POST with Json on Body - Flutter/Dart

This is my code to make a request to an 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);    });   } 

I have a problem with the response from the request, where its suppose to have a body with json, but something went wrong and i think is with the json that i send on the body request, because it is a nested json object, and the value of the key is a json object. i would love to know how i can parse the json right and insert into body of the request.

this is the header response:

 {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} 

and this is how is suppose to be:

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 

the body response came empty and i think its because the body i sent on the request, can anyone help me with the nested json object in value??

SCREENSHOT OF POSTMAN:

like image 987
Cláudio Almeida Avatar asked May 10 '18 17:05

Cláudio Almeida


People also ask

How do you get a post response on Flutter?

If you want to send an HTTP Post request in Flutter or Dart, you can use the code examples explained in this post. We are using package 'package:http/http. dart' to send a post request in Flutter. We are also sending data in our post request and getting the response in the response named variable.


2 Answers

This works!

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; } 
like image 135
Raj Yadav Avatar answered Sep 30 '22 13:09

Raj Yadav


OK, finally we have an answer...

You are correctly specifying headers: {"Content-Type": "application/json"}, to set your content type. Under the hood either the package http or the lower level dart:io HttpClient is changing this to application/json; charset=utf-8. However, your server web application obviously isn't expecting the suffix.

To prove this I tried it in Java, with the two versions

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

Are you able to contact the web application owner to explain their bug? I can't see where Dart is adding the suffix, but I'll look later.

EDIT Later investigation shows that it's the http package that, while doing a lot of the grunt work for you, is adding the suffix that your server dislikes. If you can't get them to fix the server then you can by-pass http and use the dart:io HttpClient directly. You end up with a bit of boilerplate which is normally handled for you by http.

Working example below:

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

Depending on your use case, it may be more efficient to re-use the HttpClient, rather than keep creating a new one for each request. Todo - add some error handling ;-)

like image 23
Richard Heap Avatar answered Sep 30 '22 14:09

Richard Heap