mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-07 16:23:38 +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:
parent
43d0989a3c
commit
f6516b004f
@ -34,6 +34,7 @@ enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE };
|
|||||||
#define HTTP_DOWNLOAD_UNIT_SIZE 1460
|
#define HTTP_DOWNLOAD_UNIT_SIZE 1460
|
||||||
#define HTTP_UPLOAD_BUFLEN 2048
|
#define HTTP_UPLOAD_BUFLEN 2048
|
||||||
#define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request
|
#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 HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
|
||||||
|
|
||||||
#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
|
#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
|
||||||
@ -66,13 +67,13 @@ public:
|
|||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void handleClient();
|
void handleClient();
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
bool authenticate(const char * username, const char * password);
|
bool authenticate(const char * username, const char * password);
|
||||||
void requestAuthentication();
|
void requestAuthentication();
|
||||||
|
|
||||||
typedef std::function<void(void)> THandlerFunction;
|
typedef std::function<void(void)> THandlerFunction;
|
||||||
void on(const char* uri, THandlerFunction handler);
|
void on(const char* uri, THandlerFunction handler);
|
||||||
void on(const char* uri, HTTPMethod method, THandlerFunction fn);
|
void on(const char* uri, HTTPMethod method, THandlerFunction fn);
|
||||||
|
@ -31,6 +31,38 @@
|
|||||||
#define DEBUG_OUTPUT Serial
|
#define DEBUG_OUTPUT Serial
|
||||||
#endif
|
#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) {
|
bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
|
||||||
// Read the first line of HTTP request
|
// Read the first line of HTTP request
|
||||||
String req = client.readStringUntil('\r');
|
String req = client.readStringUntil('\r');
|
||||||
@ -114,14 +146,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
|
|||||||
headerValue = req.substring(headerDiv + 1);
|
headerValue = req.substring(headerDiv + 1);
|
||||||
headerValue.trim();
|
headerValue.trim();
|
||||||
_collectHeader(headerName.c_str(),headerValue.c_str());
|
_collectHeader(headerName.c_str(),headerValue.c_str());
|
||||||
|
|
||||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||||
DEBUG_OUTPUT.print("headerName: ");
|
DEBUG_OUTPUT.print("headerName: ");
|
||||||
DEBUG_OUTPUT.println(headerName);
|
DEBUG_OUTPUT.println(headerName);
|
||||||
DEBUG_OUTPUT.print("headerValue: ");
|
DEBUG_OUTPUT.print("headerValue: ");
|
||||||
DEBUG_OUTPUT.println(headerValue);
|
DEBUG_OUTPUT.println(headerValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (headerName == "Content-Type"){
|
if (headerName == "Content-Type"){
|
||||||
if (headerValue.startsWith("text/plain")){
|
if (headerValue.startsWith("text/plain")){
|
||||||
isForm = false;
|
isForm = false;
|
||||||
@ -137,26 +169,9 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isForm){
|
if (!isForm){
|
||||||
if (searchStr != "") searchStr += '&';
|
size_t plainLength;
|
||||||
char *plainBuf = nullptr;
|
char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT);
|
||||||
size_t plainLen = 0;
|
if (plainLength < contentLength) {
|
||||||
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)
|
|
||||||
{
|
|
||||||
free(plainBuf);
|
free(plainBuf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -164,14 +179,17 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
|
|||||||
DEBUG_OUTPUT.print("Plain: ");
|
DEBUG_OUTPUT.print("Plain: ");
|
||||||
DEBUG_OUTPUT.println(plainBuf);
|
DEBUG_OUTPUT.println(plainBuf);
|
||||||
#endif
|
#endif
|
||||||
if(plainBuf[0] == '{' || plainBuf[0] == '[' || strstr(plainBuf, "=") == NULL){
|
if (contentLength > 0) {
|
||||||
//plain post json or other data
|
if (searchStr != "") searchStr += '&';
|
||||||
searchStr += "plain=";
|
if(plainBuf[0] == '{' || plainBuf[0] == '[' || strstr(plainBuf, "=") == NULL){
|
||||||
searchStr += plainBuf;
|
//plain post json or other data
|
||||||
} else {
|
searchStr += "plain=";
|
||||||
searchStr += plainBuf;
|
searchStr += plainBuf;
|
||||||
|
} else {
|
||||||
|
searchStr += plainBuf;
|
||||||
|
}
|
||||||
|
free(plainBuf);
|
||||||
}
|
}
|
||||||
free(plainBuf);
|
|
||||||
}
|
}
|
||||||
_parseArguments(searchStr);
|
_parseArguments(searchStr);
|
||||||
if (isForm){
|
if (isForm){
|
||||||
@ -194,14 +212,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
|
|||||||
headerName = req.substring(0, headerDiv);
|
headerName = req.substring(0, headerDiv);
|
||||||
headerValue = req.substring(headerDiv + 2);
|
headerValue = req.substring(headerDiv + 2);
|
||||||
_collectHeader(headerName.c_str(),headerValue.c_str());
|
_collectHeader(headerName.c_str(),headerValue.c_str());
|
||||||
|
|
||||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||||
DEBUG_OUTPUT.print("headerName: ");
|
DEBUG_OUTPUT.print("headerName: ");
|
||||||
DEBUG_OUTPUT.println(headerName);
|
DEBUG_OUTPUT.println(headerName);
|
||||||
DEBUG_OUTPUT.print("headerValue: ");
|
DEBUG_OUTPUT.print("headerValue: ");
|
||||||
DEBUG_OUTPUT.println(headerValue);
|
DEBUG_OUTPUT.println(headerValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (headerName == "Host"){
|
if (headerName == "Host"){
|
||||||
_hostHeader = headerValue;
|
_hostHeader = headerValue;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user