I am making a simple http request, and when I do, the program either throws the exception SocketException: Reading from a closed socket, or it just quietly hangs and never returns. Here is what my code looks like:
void main() async {
const url = 'https://example.com';
final client = http.Client();
var i = 0;
var count = 10;
while (i < count) {
final options = {...};
final response = await client.post(url, body: options);
// deal with response
++count
}
client.close();
}
And as I mentioned above, this hangs or throws:
Unhandled exception:
SocketException: Reading from a closed socket
#0 _RawSecureSocket.read (dart:io/secure_socket.dart:694:7)
#1 _Socket._onData (dart:io/runtime/binsocket_patch.dart:1720:27)
#2 _RootZone.runUnaryGuarded (dart:async/zone.dart:1314:10)
#3 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
#4 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
#5 _SyncStreamController._sendData (dart:async/stream_controller.dart:763:19)
#6 _StreamController._add (dart:async/stream_controller.dart:639:7)
#7 _StreamController.add (dart:async/stream_controller.dart:585:5)
#8 _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:1005:19)
#9 Timer._createTimer.<anonymous closure> (dart:async/runtime/libtimer_patch.dart:21:15)
#10 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
#11 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
#12 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
Oddly, this only seems to happen for certain URLs. Some URLs run perfectly every time, and then some cause it to hang. If it matters, I'm making POST requests to a online form.
Am I making requests too fast? The requests are in a while loop and I process the results almost immediately so it ends up making calls one after the other very fast.
Does the library discourage/prevent this? Should I add delays?
Might be related to this dropped call issue: https://github.com/dart-lang/sdk/issues/34477
I don't know what URLs you are trying to post to but maybe some of them have anti spam methods on them, which instead of showing a soft error just closes the connection to you.
final response = await http.post(...) Only succeeds if it got a response from the remote. So error handling with response.statusCode only works if you received a response from the server see codes.
The way to handle this is a try {}catch(){} block
try {
final response = await http.post(...);
/// Your code, handle soft errors here (statusCodes)
catch(error) {
/// Handle 'hard' errors here, broken connections, connection refused, etc etc
}
There is also another way, but I haven't managed to get this working and that is by using the Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
To the (edit:) flutter developers, I think that the Cookbook: Fetch data from the internet should explain error handling better, and maybe abstract the exception handling inside the package itself.
Okay I managed to make the other way work, which is prettier than a try catch block imo.
final post = client.post(url, body: options);
await get.then((response){
if (response.statusCode == 200){
// Everything okay
}else{
// soft error, see status codes
}
}, onError: (err){
// Exception error, see err.toString();
});
By the way you can skip the final client = http.Client(); and go straight to final post = http.post(url, body: options);
Yeah weird still hanging! I have the call wrapped in a try/catch already and it never throws an error, it just hangs and waits. I guess its just something about the URLs I'm trying to hit. However, the same POST requests succeed in Postman and in a Google Cloud function, which is what makes me feel like it is Dart specific.
Also, isn't using a Client better if you are making many calls to the same server and want to keep the connection open?
I receive this error intermittently when creating multiple WebSocketChannel. I have a factory function like
// ...
channelFactory: () => IOWebSocketChannel.connect(
Config.instance.apiWsHostUrl,
headers: {
'Authorization': 'Bearer $token',
},
),
// ...
Which is then opened and closed with functions like
bool open() {
if (isActive) {
return false;
}
_monitor.start();
_channel$.add(consumer.channelFactory())
_state = ConnectionState.Open;
return true;
}
bool close() {
if (!this.isActive) {
return false;
}
_monitor.stop();
_channel$.value.sink.close(status.goingAway);
_channel$.add(null);
_state = ConnectionState.Closed;
return true;
}
And after calling open() and close() in succession we get the SocketException: Reading from a closed socket error from within the WebSocket.connect call
flutter: SocketException: Reading from a closed socket
flutter: dart:_http WebSocket.connect
flutter: package:web_socket_channel/io.dart 58:19 new IOWebSocketChannel.connect
.... from that factory function call and more ....
This only happens on the second open call: the state goes like open() -> close() -> open()
@shrugs, Even we have a similar issue with our app. Have you got any lead or solution or workaround?
@kssujithcj can't remember making any progress on this, sorry
Most helpful comment
I receive this error intermittently when creating multiple
WebSocketChannel. I have a factory function likeWhich is then opened and closed with functions like
And after calling
open()andclose()in succession we get theSocketException: Reading from a closed socketerror from within theWebSocket.connectcallThis only happens on the second
opencall: the state goes likeopen() -> close() -> open()