1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

ESP8266WebServer: fix handling of empty POST

Fix handling of case when Content-Length is 0.
Change do {} while() loop into while(){} so that we don't wait 1000ms for data in case Content-Length is 0.
Also fix handling of cases when malloc or realloc return null.
This commit is contained in:
Ivan Grokhotkov 2016-04-18 10:33:10 +03:00
parent 43d0989a3c
commit f6516b004f
2 changed files with 52 additions and 33 deletions

View File

@ -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<void(void)> THandlerFunction;
void on(const char* uri, THandlerFunction handler);
void on(const char* uri, HTTPMethod method, THandlerFunction fn);

View File

@ -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;
}