HTTP POST with Json on Body - Flutter/Dart
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 ;-)
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;
}
This would also work :
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}");
});
}
I think many people have problems with Post 'Content-type': 'application / json'
The problem here is parse data Map <String, dynamic>
to json
:
Hope the code below can help someone
Model:
class ConversationReq {
String name = '';
String description = '';
String privacy = '';
String type = '';
String status = '';
String role;
List<String> members;
String conversationType = '';
ConversationReq({this.type, this.name, this.status, this.description, this.privacy, this.conversationType, this.role, this.members});
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['description'] = this.description;
data['privacy'] = this.privacy;
data['type'] = this.type;
data['conversations'] = [
{
"members": members,
"conversationType": conversationType,
}
];
return data;
}
}
Request:
createNewConversation(ConversationReq param) async {
HeaderRequestAuth headerAuth = await getAuthHeader();
var headerRequest = headerAuth.toJson();
/*
{
'Content-type': 'application/json',
'x-credential-session-token': xSectionToken,
'x-user-org-uuid': xOrg,
}
*/
var bodyValue = param.toJson();
var bodydata = json.encode(bodyValue);// important
print(bodydata);
final response = await http.post(env.BASE_API_URL + "xxx", headers: headerRequest, body: bodydata);
print(json.decode(response.body));
if (response.statusCode == 200) {
// TODO
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load ConversationRepo');
}
}