mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-23 08:45:22 +03:00
webserver hook: allow to handle external http protocol (#7459)
* webhook api * simplify webserver debug printouts, move text to flash * Hook examples in HelloServer example * print executable code address in example * simplify example per @mcspr suggestion
This commit is contained in:
@ -25,13 +25,6 @@
|
||||
#include "ESP8266WebServer.h"
|
||||
#include "detail/mimetable.h"
|
||||
|
||||
//#define DEBUG_ESP_HTTP_SERVER
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_OUTPUT DEBUG_ESP_PORT
|
||||
#else
|
||||
#define DEBUG_OUTPUT Serial
|
||||
#endif
|
||||
|
||||
#ifndef WEBSERVER_MAX_POST_ARGS
|
||||
#define WEBSERVER_MAX_POST_ARGS 32
|
||||
#endif
|
||||
@ -61,17 +54,14 @@ static bool readBytesWithTimeout(typename ServerType::ClientType& client, size_t
|
||||
}
|
||||
|
||||
template <typename ServerType>
|
||||
bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
// Read the first line of HTTP request
|
||||
String req = client.readStringUntil('\r');
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("request: ");
|
||||
DEBUG_OUTPUT.println(req);
|
||||
#endif
|
||||
DBGWS("request: %s\n", req.c_str());
|
||||
client.readStringUntil('\n');
|
||||
//reset header value
|
||||
for (int i = 0; i < _headerKeysCount; ++i) {
|
||||
_currentHeaders[i].value =String();
|
||||
_currentHeaders[i].value.clear();
|
||||
}
|
||||
|
||||
// First line of HTTP request looks like "GET /path HTTP/1.1"
|
||||
@ -79,10 +69,8 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
int addr_start = req.indexOf(' ');
|
||||
int addr_end = req.indexOf(' ', addr_start + 1);
|
||||
if (addr_start == -1 || addr_end == -1) {
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Invalid request");
|
||||
#endif
|
||||
return false;
|
||||
DBGWS("Invalid request\n");
|
||||
return CLIENT_MUST_STOP;
|
||||
}
|
||||
|
||||
String methodStr = req.substring(0, addr_start);
|
||||
@ -98,6 +86,13 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
_currentUri = url;
|
||||
_chunked = false;
|
||||
|
||||
if (_hook)
|
||||
{
|
||||
auto whatNow = _hook(methodStr, url, &client, mime::getContentType);
|
||||
if (whatNow != CLIENT_REQUEST_CAN_CONTINUE)
|
||||
return whatNow;
|
||||
}
|
||||
|
||||
HTTPMethod method = HTTP_GET;
|
||||
if (methodStr == F("HEAD")) {
|
||||
method = HTTP_HEAD;
|
||||
@ -117,14 +112,8 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
_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);
|
||||
DEBUG_OUTPUT.print(" url: ");
|
||||
DEBUG_OUTPUT.print(url);
|
||||
DEBUG_OUTPUT.print(" search: ");
|
||||
DEBUG_OUTPUT.println(searchStr);
|
||||
#endif
|
||||
DBGWS("method: %s url: %s search: %s keepAlive=: %d\n",
|
||||
methodStr.c_str(), url.c_str(), searchStr.c_str(), _keepAlive);
|
||||
|
||||
//attach handler
|
||||
RequestHandlerType* handler;
|
||||
@ -157,12 +146,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
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
|
||||
DBGWS("headerName: %s\nheaderValue: %s\n", headerName.c_str(), headerValue.c_str());
|
||||
|
||||
if (headerName.equalsIgnoreCase(FPSTR(Content_Type))){
|
||||
using namespace mime;
|
||||
@ -193,7 +177,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
)
|
||||
)
|
||||
{
|
||||
return false;
|
||||
return CLIENT_MUST_STOP;
|
||||
}
|
||||
|
||||
if (isEncoded) {
|
||||
@ -218,7 +202,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
} else { // isForm is true
|
||||
// here: content is not yet read (plainBuf is still empty)
|
||||
if (!_parseForm(client, boundaryStr, contentLength)) {
|
||||
return false;
|
||||
return CLIENT_MUST_STOP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -237,12 +221,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
headerValue = req.substring(headerDiv + 2);
|
||||
_collectHeader(headerName.c_str(),headerValue.c_str());
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print(F("headerName: "));
|
||||
DEBUG_OUTPUT.println(headerName);
|
||||
DEBUG_OUTPUT.print(F("headerValue: "));
|
||||
DEBUG_OUTPUT.println(headerValue);
|
||||
#endif
|
||||
DBGWS("headerName: %s\nheaderValue: %s\n", headerName.c_str(), headerValue.c_str());
|
||||
|
||||
if (headerName.equalsIgnoreCase(F("Host"))){
|
||||
_hostHeader = headerValue;
|
||||
@ -255,19 +234,15 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
client.flush();
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print(F("Request: "));
|
||||
DEBUG_OUTPUT.println(url);
|
||||
DEBUG_OUTPUT.print(F("Arguments: "));
|
||||
DEBUG_OUTPUT.println(searchStr);
|
||||
|
||||
DEBUG_OUTPUT.println(F("final list of key/value pairs:"));
|
||||
DBGWS("Request: %s\nArguments: %s\nfinal list of key/value pairs:\n",
|
||||
url.c_str(), searchStr.c_str());
|
||||
for (int i = 0; i < _currentArgCount; i++)
|
||||
DEBUG_OUTPUT.printf(" key:'%s' value:'%s'\r\n",
|
||||
DBGWS(" key:'%s' value:'%s'\r\n",
|
||||
_currentArgs[i].key.c_str(),
|
||||
_currentArgs[i].value.c_str());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return CLIENT_REQUEST_CAN_CONTINUE;
|
||||
}
|
||||
|
||||
template <typename ServerType>
|
||||
@ -316,10 +291,7 @@ void ESP8266WebServerTemplate<ServerType>::_parseArguments(const String& data) {
|
||||
template <typename ServerType>
|
||||
int ESP8266WebServerTemplate<ServerType>::_parseArgumentsPrivate(const String& data, std::function<void(String&,String&,const String&,int,int,int,int)> handler) {
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("args: ");
|
||||
DEBUG_OUTPUT.println(data);
|
||||
#endif
|
||||
DBGWS("args: %s\n", data.c_str());
|
||||
|
||||
size_t pos = 0;
|
||||
int arg_total = 0;
|
||||
@ -357,11 +329,7 @@ int ESP8266WebServerTemplate<ServerType>::_parseArgumentsPrivate(const String& d
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("args count: ");
|
||||
DEBUG_OUTPUT.println(arg_total);
|
||||
#endif
|
||||
|
||||
DBGWS("args count: %d\n", (int)arg_total);
|
||||
return arg_total;
|
||||
}
|
||||
|
||||
@ -390,12 +358,7 @@ uint8_t ESP8266WebServerTemplate<ServerType>::_uploadReadByte(ClientType& client
|
||||
template <typename ServerType>
|
||||
bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const String& boundary, uint32_t len){
|
||||
(void) len;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Parse Form: Boundary: ");
|
||||
DEBUG_OUTPUT.print(boundary);
|
||||
DEBUG_OUTPUT.print(" Length: ");
|
||||
DEBUG_OUTPUT.println(len);
|
||||
#endif
|
||||
DBGWS("Parse Form: Boundary: '%s' Length: %d\n", boundary.c_str(), (int)len);
|
||||
String line;
|
||||
int retry = 0;
|
||||
do {
|
||||
@ -429,18 +392,12 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
|
||||
argFilename = argName.substring(nameStart+2, argName.length() - 1);
|
||||
argName = argName.substring(0, argName.indexOf('"'));
|
||||
argIsFile = true;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg FileName: ");
|
||||
DEBUG_OUTPUT.println(argFilename);
|
||||
#endif
|
||||
DBGWS("PostArg FileName: %s\n", argFilename.c_str());
|
||||
//use GET to set the filename if uploading using blob
|
||||
if (argFilename == F("blob") && hasArg(FPSTR(filename)))
|
||||
argFilename = arg(FPSTR(filename));
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg Name: ");
|
||||
DEBUG_OUTPUT.println(argName);
|
||||
#endif
|
||||
DBGWS("PostArg Name: %s\n", argName.c_str());
|
||||
using namespace mime;
|
||||
argType = FPSTR(mimeTable[txt].mimeType);
|
||||
line = client.readStringUntil('\r');
|
||||
@ -451,10 +408,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
|
||||
client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg Type: ");
|
||||
DEBUG_OUTPUT.println(argType);
|
||||
#endif
|
||||
DBGWS("PostArg Type: %s\n", argType.c_str());
|
||||
if (!argIsFile){
|
||||
while(1){
|
||||
line = client.readStringUntil('\r');
|
||||
@ -463,20 +417,14 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
|
||||
if (argValue.length() > 0) argValue += '\n';
|
||||
argValue += line;
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg Value: ");
|
||||
DEBUG_OUTPUT.println(argValue);
|
||||
DEBUG_OUTPUT.println();
|
||||
#endif
|
||||
DBGWS("PostArg Value: %s\n\n", argValue.c_str());
|
||||
|
||||
RequestArgument& arg = _postArgs[_postArgsLen++];
|
||||
arg.key = argName;
|
||||
arg.value = argValue;
|
||||
|
||||
if (line == ("--"+boundary+"--")){
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Done Parsing POST");
|
||||
#endif
|
||||
DBGWS("Done Parsing POST\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -488,12 +436,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
|
||||
_currentUpload->totalSize = 0;
|
||||
_currentUpload->currentSize = 0;
|
||||
_currentUpload->contentLength = len;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Start File: ");
|
||||
DEBUG_OUTPUT.print(_currentUpload->filename);
|
||||
DEBUG_OUTPUT.print(" Type: ");
|
||||
DEBUG_OUTPUT.println(_currentUpload->type);
|
||||
#endif
|
||||
DBGWS("Start File: %s Type: %s\n", _currentUpload->filename.c_str(), _currentUpload->type.c_str());
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, *_currentUpload);
|
||||
_currentUpload->status = UPLOAD_FILE_WRITE;
|
||||
@ -537,20 +480,14 @@ readfile:
|
||||
_currentUpload->status = UPLOAD_FILE_END;
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, *_currentUpload);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("End File: ");
|
||||
DEBUG_OUTPUT.print(_currentUpload->filename);
|
||||
DEBUG_OUTPUT.print(" Type: ");
|
||||
DEBUG_OUTPUT.print(_currentUpload->type);
|
||||
DEBUG_OUTPUT.print(" Size: ");
|
||||
DEBUG_OUTPUT.println(_currentUpload->totalSize);
|
||||
#endif
|
||||
DBGWS("End File: %s Type: %s Size: %d\n",
|
||||
_currentUpload->filename.c_str(),
|
||||
_currentUpload->type.c_str(),
|
||||
(int)_currentUpload->totalSize);
|
||||
line = client.readStringUntil(0x0D);
|
||||
client.readStringUntil(0x0A);
|
||||
if (line == "--"){
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Done Parsing POST");
|
||||
#endif
|
||||
DBGWS("Done Parsing POST\n");
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@ -598,10 +535,7 @@ readfile:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Error: line: ");
|
||||
DEBUG_OUTPUT.println(line);
|
||||
#endif
|
||||
DBGWS("Error: line: %s\n", line.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user