Flutter Dart - How to send a Post Request using HttpClient() - http

I am trying to send a Post request to my server using HttpClient but I am not sure where to actually set the payload and headers that need to be sent.
var client = new HttpClient();
client.post(host, port, path);
client.post(host, port, path) has only 3 arguments so how do I set the payload to be sent?
Thanks in advance

post() opens a HTTP connection using the POST method and returns Future<HttpClientRequest>.
So you need to do this:
final client = HttpClient();
final request = await client.post(host, port, path);
request.headers.set(HttpHeaders.contentTypeHeader, "plain/text"); // or headers.add()
final response = await request.close();
Example with jsonplaceholder:
final client = HttpClient();
final request = await client.postUrl(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
request.headers.set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8");
request.write('{"title": "Foo","body": "Bar", "userId": 99}');
final response = await request.close();
response.transform(utf8.decoder).listen((contents) {
print(contents);
});
prints
{
"title": "Foo",
"body": "Bar",
"userId": 99,
"id": 101
}
Or you can use http library.

String url =
'http://wwww.foo.com';
http.get(url).then((http.Response response) {
is_loading=true;
// print(json.decode(response.body));
Map<String, dynamic> Data = json.decode(response.body);
Data.forEach((String data, dynamic data_value) {
print(data + " : ");
print(data_value.toString());
// Map<String,String> decoded_data=json.decode(data);
// print(data_value.toString());
//print(data['title']);
//print(data['content']);
});

Related

Why .NET CORE HttpClient takes exactly 15 seconds to resolve an API Gateway?

In my .net-core, I'm calling diffrent external API's.
If the API is in the same cluster, I'm getting an immediate response. But If the external API is hosted through an internal gateway, It takes exactly 15 seconds to send the request to the internal gateway.
I tried to call this specific API directly from my docker terminal and its receiving the request immediately. Also checked the internal gateway logs and the request is only receiving after 15 seconds after I made a request from the code.
Here is my code.
HttpClientHandler clientHandlerCustPortfolioSecurityHoldings = new() {
UseProxy = false,
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
return true;
}
};
using(var httpClient = new HttpClient(clientHandlerCustPortfolioSecurityHoldings)) {
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Bearer token");
httpClient.DefaultRequestHeaders.Add("ClientId", "test data");
httpClient.DefaultRequestHeaders.Add("X-USER-ID", "test data");
httpClient.DefaultRequestHeaders.Add("X-ORG-ID", "test data");
httpClient.DefaultRequestHeaders.Add("X-MSG-ID", "test data");
httpClient.Timeout = TimeSpan.FromSeconds(int.Parse(_config["EXT_API_TIMEOUT_IN_SECONDS"]));
StringContent InputContent = new(JsonSerializer.Serialize(reqparams), Encoding.UTF8, "application/json");
using(var response = await httpClient.PostAsync("https internal gateway URL", InputContent)) {
if (response.IsSuccessStatusCode) {
var result = await response.Content.ReadAsStringAsync();
APICustomResponse apiCustomResponse = new() {
StatusCode = true,
ErrorMessage = "Success",
ResponseData = result
};
return await Task.FromResult(apiCustomResponse);
} else {
var result = await response.Content.ReadAsStringAsync();
APICustomResponse apiCustomResponse = new() {
StatusCode = false,
ErrorMessage = "Failed",
ResponseData = result
};
return await Task.FromResult(apiCustomResponse);
}
}
}
Please help me out. It is this constant 15 seconds thing is killing me.

Token Post Request With Flutter dart:io Invalid

I'm doing a post request to an ASP.Net Web API to acquire a token. I am able to do this successfully with the dart HTTP package as follow:
Uri address = Uri.parse('https://myaddress:myport/token');
var response = await http.post(
address,
body: {
'username': 'MyUsername',
'password': 'MyPassword',
'grant_type': 'password'
},
).timeout(Duration(seconds: 20));
return response.body;
No problem with Postman either:
Now I want to do the same with the base dart:io class, as the testing server has a self signed certificate which I found the HTTP package has no bypass for (might be wrong), but for the life of me I cannot figure out where I am going wrong as when I debug the server the requests never get hit with the following code:
Uri address = Uri.parse('https://myaddress:myport/token');
HttpClient httpClient = HttpClient();
httpClient.connectionTimeout = Duration(seconds: 20);
httpClient.badCertificateCallback = ((X509Certificate cert, String host, int port) => true); // Allow self signed certificates
HttpClientRequest request = await httpClient.postUrl(address);
final Map<String, String> payLoad = {
'username': 'MyUsername',
'password': 'MyPassword',
'grant_type': 'password'
};
request.headers.contentType = new ContentType("application", "x-www-form-urlencoded", charset: "utf-8");
request.add(utf8.encode(json.encode(payLoad)));
// request.write(payLoad);
HttpClientResponse response = await request.close();
String responseBody = await response.transform(utf8.decoder).join();
httpClient.close();
responseBody is always:
"{"error":"unsupported_grant_type"}"
So I assume my encoding or structure is wrong, but with all possibilities I have tried, nothing works, any help would be appreciated.
i did the same but in my case i am requesting a soap web service, the bellow code do the job for me i hope it will for you
Future<XmlDocument> sendSoapRequest(String dataRequest) async {
final startTime = Stopwatch()..start();
_attemptsRequest = 0;
bool successful = false;
String dataResponse;
try {
Uri uri = Uri.parse('https://address:port/ADService');
var httpClient = HttpClient();
httpClient.connectionTimeout = Duration(milliseconds: 5000);
httpClient.idleTimeout = Duration(milliseconds: 5000);
httpClient.badCertificateCallback = ((X509Certificate cert, String host, int port) => true); // Allow self signed certificates
await httpClient
.openUrl('POST', uri)
.then((HttpClientRequest request) async {
request.headers.contentType =
new ContentType('application', 'text/xml', charset: 'UTF-8');
_attemptsRequest++;
request.write(dataRequest);
await request.close().then((HttpClientResponse response) async {
// var data = await response.transform(utf8.decoder).join();
// i didn't use this method cause it disorganize the response when there is high level of data, -i get binary data from the server-
var data = await utf8.decoder.bind(response).toList();
dataResponse = data.join();
successful = true;
httpClient.close();
});
_timeRequest = startTime.elapsed.inMilliseconds;
});
} catch (e) {
if (_attemptsRequest >= getAttempts) {
_timeRequest = startTime.elapsed.inMilliseconds;
if (e is SocketException)
throw Exception('Timeout exception, operation has expired: $e');
throw Exception('Error sending request: $e');
} else {
sleep(const Duration(milliseconds: 500));
}
}
try {
if (successful) {
XmlDocument doc;
doc = parse(dataResponse);
return doc;
} else {
return null;
}
} catch (e) {
throw Exception('Error converting response to Document: $e');
}
}

How to read Http response from flutter?

I'm trying to read reponse from HTTP in flutter but I didnt read.
I posted the request. Can anyone know, what is wrong ?
final http.Client client;
Future<http.Response> post(
Uri uri, {
Map<String, dynamic> postParams,
String accessToken,
}) async {
log.info(uri.toString());
log.info('postParams: ${postParams?.toString()}');
///Encode map to bytes
String jsonString = json.encode(postParams);
List<int> bodyBytes = utf8.encode(jsonString);
Map headers = {
HttpHeaders.contentTypeHeader: 'application/json; charset=utf-8',
};
final response = await client
.post(
uri,
body: bodyBytes,
headers: headers,
)
.timeout(Duration(seconds: 120));
}
You can achieve this functionality as follow
1.install http package and import it as follow
import 'package:http/http.dart' as http;
Create an instance of http or http.Client as you did
final http.Client _client = http.Client();
Send the request to server as follow
var url = 'https://example.com/store/.....';
final Map<String, dynamic> data= {"name":"John Doe", "email":"johndoe#email.com"};
final Map<String, String> _headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
var response = await _client.post(url, body:data, headers:_headers);
Then you can read the response as
if(response.statusCode == 200) {
var decoded = json.decode(response.body);
print(decoded);
// The Rest of code
}

How to set Timeout for MultiPart Request in Dart?

Here is my MultiPartRequest code
var request =
http.MultipartRequest("POST", Uri.parse(EMPLOYEE_PUNCH_IN_URL));
request.fields['uid'] = userId;
request.fields['location'] = location;
request.fields['punchin_time'] = punchInTime;
request.fields['punchin_location_name'] = address;
var multiPartFile = await http.MultipartFile.fromPath(
"photo", imageFile.path,
contentType: MediaType("image", "$extension"));
request.files.add(multiPartFile);
http.StreamedResponse response = await request.send();
var responseByteArray = await response.stream.toBytes();
employeePunchInModel = standardSerializers.deserializeWith(
EmployeePunchInModel.serializer,
json.decode(utf8.decode(responseByteArray)));
......
I know how to set timeout to a normal http request. I have followed this link
Set timeout for HTTPClient get() request
I have tried adding timeout function in following ways but it won't work and my request gets completed
1.
var multiPartFile = await http.MultipartFile.fromPath(
"photo", imageFile.path,
contentType: MediaType("image", "$extension")).timeout(const Duration(seconds: 1));
2.
http.StreamedResponse response = await request.send().timeout(const Duration(seconds: 1));
3.
var responseByteArray = await response.stream.toBytes().timeout(const Duration(seconds: 15));
But none of the above timeout works.
Using http package, this is my approach :
Create a Streamed Response that we're going to use for onTimeOut callback
StreamedResponse timeOutResponse({
#required String httpMethod,
#required dynamic error,
#required String url,
}) {
Map<String, dynamic> body = {
'any': 'value',
'you': 'want for $error',
};
int statusCode = 404;
Uri destination = Uri.parse(url);
String json = jsonEncode(body);
return StreamedResponse(
Stream.value(json.codeUnits),
statusCode,
request: Request(httpMethod, destination),
);
}
Use the modified http multipart function from Mahesh Jamdade answer
Future<http.Response> makeAnyHttpRequest(String url,
Map<String, dynamic> body,
{Function onTimeout,
Duration duration = const Duration(seconds: 10)}) async {
final request = http.MultipartRequest(
'POST',
Uri.parse('$url'),
);
final res = await request.send().timeout(
duration,
onTimeout: () {
return timeOutResponse(
httpMethod: 'MULTIPART POST',
error: 'Request Time Out',
url: url,
);
},
);
return await http.Response.fromStream(res);
}
this way, instead of timeout exception, you can return the onTimeOut Http Response.
Use Dio package with following code:
try {
final response = await Dio().post(requestFinal.item1, data:formData, options: option,
onSendProgress: (sent, total) {
print("uploadFile ${sent / total}");
});
print("Response Status code:: ${response.statusCode}");
if (response.statusCode >= 200 && response.statusCode < 299) {
dynamic jsonResponse = response.data;
print("response body :: $jsonResponse");
final message = jsonResponse["msg"] ?? '';
final status = jsonResponse["status"] ?? 400;
final data = jsonResponse["data"];
return HttpResponse(status: status, errMessage: message, json: data);
}
else {
dynamic jsonResponse = response.data;
print('*********************************************************');
print("response body :: $jsonResponse");
print('*********************************************************');
var errMessage = jsonResponse["msg"];
return HttpResponse(status: response.statusCode, errMessage: errMessage, json: jsonResponse);
}
}
on DioError catch(error) {
print('*********************************************************');
print('Error Details :: ${error.message}');
print('*********************************************************');
dynamic jsonResponse = error.response.data;
print('*********************************************************');
print("response body :: $jsonResponse");
print('*********************************************************');
var errMessage = jsonResponse["message"] ?? "Something went wrong";
return HttpResponse(status: jsonResponse["status"] , errMessage: errMessage, json: null);
}
Hope this helps!
I suggest that
var request = http.MultipartRequest("POST", Uri.parse(EMPLOYEE_PUNCH_IN_URL));
request.fields['uid'] = userId;
request.fields['location'] = location;
request.fields['punchin_time'] = punchInTime;
request.fields['punchin_location_name'] = address;
var multiPartFile = await http.MultipartFile.fromPath(
"photo", imageFile.path,
contentType: MediaType("image", "$extension"));
request.files.add(multiPartFile);
await request.send().timeout(Duration(seconds: 1), onTimeout: () {
throw "TimeOut";
}).then((onValue) {
var responseByteArray = await onValue.stream.toBytes();
employeePunchInModel = standardSerializers.deserializeWith(
EmployeePunchInModel.serializer,
json.decode(utf8.decode(responseByteArray)));
}).catchError((){ throw "TimeOut";});
hey you can also use dio 3.0.4
A powerful Http client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc.
Here is the link :Http client for Dart
You can try this which uses http package
declare your multipart function like this with your desired arguments
Future<http.Response> makeAnyHttpRequest(String url,
Map<String, dynamic> body,
{Function onTimeout,
Duration duration = const Duration(seconds: 10)}) async {
final request = http.MultipartRequest(
'POST',
Uri.parse('$url'),
);
final res = await request.send().timeout(duration, onTimeout: onTimeout);
return await http.Response.fromStream(res);
}
and then call it within a try catch block and you can catch the timeout exception by throwing the desired value on Timeout.
try{
final res = makeAnyHttpRequest("<url>",{"body":"here"},onTimeout:(){
throw 'TIME_OUT'; // Throw anything
});
}catch(_){
if (_.toString() == 'TIME_OUT') { // catch the thrown value to detect TIMEOUT
/// DO SOMETHING ON TIMEOUT
debugPrint('The request Timeout');
}
}
}
The above approach would work for any http request as long as you have a onTimeout call back

Why dio posts empty form data?

I have a function to upload an image but the server does not receive anything and I get 500 status code. I'm sure that the server is fine. It works when I send a post request from the postman!
This is my function:
uploadPrescriptionToAll(File file, data) async {
String convertedFilePath = await convertImage(file);
String token = await getToken();
Response response;
Dio dio = Dio();
dio.options.baseUrl = "http://x.x.x.x:x";
FormData formData = FormData.from({
"image":
UploadFileInfo(new File(convertedFilePath), "image.jpg"),
"data": data,
});
try {
response = await dio.post("/api/images",
data: formData,
options: Options(headers: {
"Authorization": token,
"Content-Type": "multipart/form-data"
}));
} catch (e) {
print("Error Upload: " + e.toString());
}
print("Response Upload:" + response.toString());
}
how can I post the file (form-data) correctly? Is there another way to do it?
Using Dio It's very simple by using : FormData.fromMap()
searchCityByName(String city) async {
Dio dio = new Dio();
var a = {"city": city};
var res = await dio.post(apiSearchState, data:FormData.fromMap(a));
}
In short, you should pass a Map<String, dynamic> object to dio.post()'s data field. For example:
response = await dio.post("/api/images",
data: {"image": "image.jpg", "data": data});
See: https://github.com/flutterchina/dio/issues/88 for details

Resources