-
Notifications
You must be signed in to change notification settings - Fork 151
Description
Summary
On iOS Safari, rapidly switching between pages that use WebSockets can leave connections half-open.
With ESPAsyncWebServer this may cause new WebSocket connections to stay stuck in CONNECTING, while desktop browsers work fine.
Root cause
AsyncWebSocket does not automatically clean up stale/half-open clients.
On iOS Safari, disconnect events are often delayed or missing during quick navigation, so stale clients accumulate unless cleanupClients() is called manually.
Fix
- Expose cleanup in WebSocketTxRx.h
Add a public loop() method to periodically clean up clients:
// WebSocketTxRx.h
public:
void loop() {
_webSocket.cleanupClients();
}
- Call cleanup from the owning service
Example using LightStateService:
// LightStateService.h
public:
void loop();
// LightStateService.cpp
void LightStateService::loop() {
_webSocket.loop();
}
- Then call this once per main loop:
// main.cpp
void loop() {
lightStateService.loop();
}
Conclusion
I’m not entirely sure this is the best or intended way to handle WebSocket lifecycle management in ESPAsyncWebServer.
However, in practice this change consistently resolves the issue on iOS Safari and prevents connections from getting stuck in CONNECTING during rapid navigation.
If there is a more idiomatic or built-in approach to handle stale WebSocket clients—especially for mobile browsers—I’d be very interested to learn about it.