I am having hard times with figuring out how to handle exceptions and closed connections using Flutter http package https://pub.dev/packages/http.
I have setup timeout of 10 sec and want to show some response to a user within that 10 sec. There is CircularProgreseIndicator
and activated by isLoading
variable, with error text wrapped up in UI for better presentation.
This example below will timeout after 10 seconds, but after around 20-30 sec, app will crash with an error Connection closed before full header was received
Same error will be thrown if I use client.close() (including finally
section).
I would like to control timeout time (4-5 sec) and close connection if no response is received within 5 sec. I don't want to implement automatic retry (want to use pull to refresh/retry manually etc.)
Would anyone know how to implement client.close()
properly? Thx
Example:
Future<String> getData() async {
final client = http.Client();
try {
var response = await client.get(Uri.parse(endpoint)).timeout(
Duration(seconds: 10),
onTimeout: () {
// Closing client here throwns an error
// client.close(); // Connection closed before full header was received
return http.Response('Error', 500); // Replace 500 with your http code.
},
);
// Some logic for state etc.
if (response.statusCode == 200) {
this.setState(() {
data = jsonDecode(response.body);
isLoading = false;
isError = false;
});
return "success";
} else {
// Closing client here throwns an error
// client.close(); // Connection closed before full header was received
setState(() {
isLoading = false;
isError = true;
});
return "error";
}
// Finally... close connection
} finally {
// Closing client here throwns an error
// client.close(); // Connection closed before full header was received
}
}
UPDATE: (workaround)
I have found a bit different approach and app does not crash with example below. Loading will be shown all the time if there is no communication with the server (no internet connection). If server returns anything but 200 (ok), "Server error occurred" will be shown.
Future<String> getData() async {
String category = await getCategory();
String endpoint =
Endpoints().getEndpoint("apiServer") + '/categories/' + category;
final client = RetryClient(http.Client());
try {
var response = await client.get(Uri.parse(endpoint));
// Added extra loading time for better UI
await Future.delayed(const Duration(milliseconds: 700), () {});
if (response.statusCode == 200) {
this.setState(() {
data = jsonDecode(response.body);
isLoading = false;
});
showSnackbar("success", "Category list retreived");
return "success";
} else {
// client.close(); // Connection closed before full header was received
setState(() {
isLoading = false;
isError = true;
});
showSnackbar("error", "Server error occurred. Try again");
return "error";
}
} finally {
client.close();
}
}