diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 4e291e5fb..f94cfb07f 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -34,6 +34,7 @@ enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE }; #define HTTP_DOWNLOAD_UNIT_SIZE 1460 #define HTTP_UPLOAD_BUFLEN 2048 #define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request +#define HTTP_MAX_POST_WAIT 1000 //ms to wait for POST data to arrive #define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection #define CONTENT_LENGTH_UNKNOWN ((size_t) -1) @@ -66,13 +67,13 @@ public: void begin(); void handleClient(); - + void close(); void stop(); bool authenticate(const char * username, const char * password); void requestAuthentication(); - + typedef std::function THandlerFunction; void on(const char* uri, THandlerFunction handler); void on(const char* uri, HTTPMethod method, THandlerFunction fn); diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 519918308..f4fff1765 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -31,6 +31,38 @@ #define DEBUG_OUTPUT Serial #endif +static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms) +{ + char *buf = nullptr; + dataLength = 0; + while (dataLength < maxLength) { + int tries = timeout_ms; + size_t newLength; + while (!(newLength = client.available()) && tries--) delay(1); + if (!newLength) { + break; + } + if (!buf) { + buf = (char *) malloc(newLength + 1); + if (!buf) { + return nullptr; + } + } + else { + char* newBuf = (char *) realloc(buf, dataLength + newLength + 1); + if (!newBuf) { + free(buf); + return nullptr; + } + buf = newBuf; + } + client.readBytes(buf + dataLength, newLength); + dataLength += newLength; + buf[dataLength] = '\0'; + } + return buf; +} + bool ESP8266WebServer::_parseRequest(WiFiClient& client) { // Read the first line of HTTP request String req = client.readStringUntil('\r'); @@ -114,14 +146,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { headerValue = req.substring(headerDiv + 1); headerValue.trim(); _collectHeader(headerName.c_str(),headerValue.c_str()); - + #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("headerName: "); DEBUG_OUTPUT.println(headerName); DEBUG_OUTPUT.print("headerValue: "); DEBUG_OUTPUT.println(headerValue); #endif - + if (headerName == "Content-Type"){ if (headerValue.startsWith("text/plain")){ isForm = false; @@ -137,26 +169,9 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { } if (!isForm){ - if (searchStr != "") searchStr += '&'; - char *plainBuf = nullptr; - size_t plainLen = 0; - do - { - //some clients send headers first and data after (like we do) - //give them a chance - int tries = 1000;//1000ms max wait - size_t newLen; - while( !(newLen = client.available()) && tries--) delay(1); - if (!newLen) break; - plainBuf = (plainBuf == nullptr) ? (char *) malloc(newLen + 1) : (char *) realloc(plainBuf, plainLen + newLen + 1); - client.readBytes(&plainBuf[plainLen], newLen); - plainLen += newLen; - plainBuf[plainLen] = '\0'; - } while (plainLen < contentLength); - /* if data loss, exit */ - if (plainBuf == nullptr) return false; - if (plainLen < contentLength) - { + size_t plainLength; + char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT); + if (plainLength < contentLength) { free(plainBuf); return false; } @@ -164,14 +179,17 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { DEBUG_OUTPUT.print("Plain: "); DEBUG_OUTPUT.println(plainBuf); #endif - if(plainBuf[0] == '{' || plainBuf[0] == '[' || strstr(plainBuf, "=") == NULL){ - //plain post json or other data - searchStr += "plain="; - searchStr += plainBuf; - } else { - searchStr += plainBuf; + if (contentLength > 0) { + if (searchStr != "") searchStr += '&'; + if(plainBuf[0] == '{' || plainBuf[0] == '[' || strstr(plainBuf, "=") == NULL){ + //plain post json or other data + searchStr += "plain="; + searchStr += plainBuf; + } else { + searchStr += plainBuf; + } + free(plainBuf); } - free(plainBuf); } _parseArguments(searchStr); if (isForm){ @@ -194,14 +212,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { headerName = req.substring(0, headerDiv); headerValue = req.substring(headerDiv + 2); _collectHeader(headerName.c_str(),headerValue.c_str()); - + #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("headerName: "); DEBUG_OUTPUT.println(headerName); DEBUG_OUTPUT.print("headerValue: "); DEBUG_OUTPUT.println(headerValue); #endif - + if (headerName == "Host"){ _hostHeader = headerValue; }