diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index 550376abd..ddde5756e 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -49,6 +49,7 @@ ESP8266WebServerTemplate::ESP8266WebServerTemplate(IPAddress addr, i , _currentVersion(0) , _currentStatus(HC_NONE) , _statusChange(0) +, _keepAlive(false) , _currentHandler(nullptr) , _firstHandler(nullptr) , _lastHandler(nullptr) @@ -327,6 +328,10 @@ void ESP8266WebServerTemplate::handleClient() { bool callYield = false; if (_currentClient.connected() || _currentClient.available()) { + if (_currentClient.available() && _keepAlive) { + _currentStatus = HC_WAIT_READ; + } + switch (_currentStatus) { case HC_NONE: // No-op to avoid C++ compiler warning @@ -431,7 +436,14 @@ void ESP8266WebServerTemplate::_prepareHeader(String& response, int if (_corsEnabled) { sendHeader(String(F("Access-Control-Allow-Origin")), String("*")); } - sendHeader(String(F("Connection")), String(F("close"))); + + if (_keepAlive && _server.hasClient()) { // Disable keep alive if another client is waiting. + _keepAlive = false; + } + sendHeader(String(F("Connection")), String(_keepAlive ? F("keep-alive") : F("close"))); + if (_keepAlive) { + sendHeader(String(F("Keep-Alive")), String(F("timeout=")) + HTTP_MAX_CLOSE_WAIT); + } response += _responseHeaders; response += "\r\n"; diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 85eab1b7d..59c1ad687 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -168,6 +168,14 @@ public: sendContent(emptyString); } + // Whether other requests should be accepted from the client on the + // same socket after a response is sent. + // This will automatically configure the "Connection" header of the response. + // Defaults to true when the client's HTTP version is 1.1 or above, otherwise it defaults to false. + // If the client sends the "Connection" header, the value given by the header is used. + void keepAlive(bool keepAlive) { _keepAlive = keepAlive; } + bool keepAlive() { return _keepAlive; } + static String credentialHash(const String& username, const String& realm, const String& password); static String urlDecode(const String& text); @@ -224,6 +232,7 @@ protected: uint8_t _currentVersion; HTTPClientStatus _currentStatus; unsigned long _statusChange; + bool _keepAlive; RequestHandlerType* _currentHandler; RequestHandlerType* _firstHandler; diff --git a/libraries/ESP8266WebServer/src/Parsing-impl.h b/libraries/ESP8266WebServer/src/Parsing-impl.h index 6c96d564a..8d3fda278 100644 --- a/libraries/ESP8266WebServer/src/Parsing-impl.h +++ b/libraries/ESP8266WebServer/src/Parsing-impl.h @@ -114,6 +114,9 @@ bool ESP8266WebServerTemplate::_parseRequest(ClientType& client) { } _currentMethod = method; + _keepAlive = _currentVersion > 0; // Keep the connection alive by default + // if the protocol version is greater than HTTP 1.0 + #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("method: "); DEBUG_OUTPUT.print(methodStr); @@ -144,7 +147,7 @@ bool ESP8266WebServerTemplate::_parseRequest(ClientType& client) { while(1){ req = client.readStringUntil('\r'); client.readStringUntil('\n'); - if (req.isEmpty()) break;//no moar headers + if (req.isEmpty()) break; //no more headers int headerDiv = req.indexOf(':'); if (headerDiv == -1){ break; @@ -177,6 +180,8 @@ bool ESP8266WebServerTemplate::_parseRequest(ClientType& client) { contentLength = headerValue.toInt(); } else if (headerName.equalsIgnoreCase(F("Host"))){ _hostHeader = headerValue; + } else if (headerName.equalsIgnoreCase(F("Connection"))){ + _keepAlive = headerValue.equalsIgnoreCase(F("keep-alive")); } } @@ -241,6 +246,8 @@ bool ESP8266WebServerTemplate::_parseRequest(ClientType& client) { if (headerName.equalsIgnoreCase(F("Host"))){ _hostHeader = headerValue; + } else if (headerName.equalsIgnoreCase(F("Connection"))){ + _keepAlive = headerValue.equalsIgnoreCase(F("keep-alive")); } } _parseArguments(searchStr);