mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-15 00:02:49 +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:
@ -28,20 +28,12 @@
|
||||
#include "FS.h"
|
||||
#include "detail/RequestHandlersImpl.h"
|
||||
|
||||
//#define DEBUG_ESP_HTTP_SERVER
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_OUTPUT DEBUG_ESP_PORT
|
||||
#else
|
||||
#define DEBUG_OUTPUT Serial
|
||||
#endif
|
||||
|
||||
static const char AUTHORIZATION_HEADER[] PROGMEM = "Authorization";
|
||||
static const char qop_auth[] PROGMEM = "qop=auth";
|
||||
static const char qop_auth_quoted[] PROGMEM = "qop=\"auth\"";
|
||||
static const char WWW_Authenticate[] PROGMEM = "WWW-Authenticate";
|
||||
static const char Content_Length[] PROGMEM = "Content-Length";
|
||||
|
||||
|
||||
template <typename ServerType>
|
||||
ESP8266WebServerTemplate<ServerType>::ESP8266WebServerTemplate(IPAddress addr, int port)
|
||||
: _server(addr, port)
|
||||
@ -171,9 +163,7 @@ bool ESP8266WebServerTemplate<ServerType>::authenticateDigest(const String& user
|
||||
String authReq = header(FPSTR(AUTHORIZATION_HEADER));
|
||||
if(authReq.startsWith(F("Digest"))) {
|
||||
authReq = authReq.substring(7);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println(authReq);
|
||||
#endif
|
||||
DBGWS("%s\n", authReq.c_str());
|
||||
String _username = _extractParam(authReq,F("username=\""));
|
||||
if(!_username.length() || _username != String(username)) {
|
||||
authReq = "";
|
||||
@ -200,9 +190,7 @@ bool ESP8266WebServerTemplate<ServerType>::authenticateDigest(const String& user
|
||||
_nc = _extractParam(authReq, F("nc="), ',');
|
||||
_cnonce = _extractParam(authReq, F("cnonce=\""));
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Hash of user:realm:pass=" + H1);
|
||||
#endif
|
||||
DBGWS("Hash of user:realm:pass=%s\n", H1.c_str());
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
if(_currentMethod == HTTP_GET){
|
||||
@ -218,9 +206,7 @@ bool ESP8266WebServerTemplate<ServerType>::authenticateDigest(const String& user
|
||||
}
|
||||
md5.calculate();
|
||||
String _H2 = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Hash of GET:uri=" + _H2);
|
||||
#endif
|
||||
DBGWS("Hash of GET:uri=%s\n", _H2.c_str());
|
||||
md5.begin();
|
||||
if(authReq.indexOf(FPSTR(qop_auth)) != -1 || authReq.indexOf(FPSTR(qop_auth_quoted)) != -1) {
|
||||
md5.add(H1 + ':' + _nonce + ':' + _nc + ':' + _cnonce + F(":auth:") + _H2);
|
||||
@ -229,9 +215,7 @@ bool ESP8266WebServerTemplate<ServerType>::authenticateDigest(const String& user
|
||||
}
|
||||
md5.calculate();
|
||||
String _responsecheck = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("The Proper response=" +_responsecheck);
|
||||
#endif
|
||||
DBGWS("The Proper response=%s\n", _responsecheck.c_str());
|
||||
if(_response == _responsecheck){
|
||||
authReq = "";
|
||||
return true;
|
||||
@ -315,9 +299,7 @@ void ESP8266WebServerTemplate<ServerType>::handleClient() {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("New client");
|
||||
#endif
|
||||
DBGWS("New client\n");
|
||||
|
||||
_currentClient = client;
|
||||
_currentStatus = HC_WAIT_READ;
|
||||
@ -327,6 +309,13 @@ void ESP8266WebServerTemplate<ServerType>::handleClient() {
|
||||
bool keepCurrentClient = false;
|
||||
bool callYield = false;
|
||||
|
||||
DBGWS("http-server loop: conn=%d avail=%d status=%s\n",
|
||||
_currentClient.connected(), _currentClient.available(),
|
||||
_currentStatus==HC_NONE?"none":
|
||||
_currentStatus==HC_WAIT_READ?"wait-read":
|
||||
_currentStatus==HC_WAIT_CLOSE?"wait-close":
|
||||
"??");
|
||||
|
||||
if (_currentClient.connected() || _currentClient.available()) {
|
||||
if (_currentClient.available() && _keepAlive) {
|
||||
_currentStatus = HC_WAIT_READ;
|
||||
@ -339,34 +328,57 @@ void ESP8266WebServerTemplate<ServerType>::handleClient() {
|
||||
case HC_WAIT_READ:
|
||||
// Wait for data from client to become available
|
||||
if (_currentClient.available()) {
|
||||
if (_parseRequest(_currentClient)) {
|
||||
switch (_parseRequest(_currentClient))
|
||||
{
|
||||
case CLIENT_REQUEST_CAN_CONTINUE:
|
||||
_currentClient.setTimeout(HTTP_MAX_SEND_WAIT);
|
||||
_contentLength = CONTENT_LENGTH_NOT_SET;
|
||||
_handleRequest();
|
||||
|
||||
if (_currentClient.connected()) {
|
||||
/* fallthrough */
|
||||
case CLIENT_REQUEST_IS_HANDLED:
|
||||
if (_currentClient.connected() || _currentClient.available()) {
|
||||
_currentStatus = HC_WAIT_CLOSE;
|
||||
_statusChange = millis();
|
||||
keepCurrentClient = true;
|
||||
}
|
||||
}
|
||||
} else { // !_currentClient.available()
|
||||
else
|
||||
DBGWS("webserver: peer has closed after served\n");
|
||||
break;
|
||||
case CLIENT_MUST_STOP:
|
||||
DBGWS("Close client\n");
|
||||
_currentClient.stop();
|
||||
break;
|
||||
case CLIENT_IS_GIVEN:
|
||||
// client must not be stopped but must not be handled here anymore
|
||||
// (example: tcp connection given to websocket)
|
||||
DBGWS("Give client\n");
|
||||
break;
|
||||
} // switch _parseRequest()
|
||||
} else {
|
||||
// !_currentClient.available(): waiting for more data
|
||||
if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) {
|
||||
keepCurrentClient = true;
|
||||
}
|
||||
else
|
||||
DBGWS("webserver: closing after read timeout\n");
|
||||
callYield = true;
|
||||
}
|
||||
break;
|
||||
case HC_WAIT_CLOSE:
|
||||
// Wait for client to close the connection
|
||||
if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) {
|
||||
if (!_server.available() && (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT)) {
|
||||
keepCurrentClient = true;
|
||||
callYield = true;
|
||||
if (_currentClient.available())
|
||||
// continue serving current client
|
||||
_currentStatus = HC_WAIT_READ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // switch _currentStatus
|
||||
}
|
||||
|
||||
if (!keepCurrentClient) {
|
||||
DBGWS("Drop client\n");
|
||||
_currentClient = ClientType();
|
||||
_currentStatus = HC_NONE;
|
||||
_currentUpload.reset();
|
||||
@ -687,17 +699,13 @@ template <typename ServerType>
|
||||
void ESP8266WebServerTemplate<ServerType>::_handleRequest() {
|
||||
bool handled = false;
|
||||
if (!_currentHandler){
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("request handler not found");
|
||||
#endif
|
||||
DBGWS("request handler not found\n");
|
||||
}
|
||||
else {
|
||||
handled = _currentHandler->handle(*this, _currentMethod, _currentUri);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
if (!handled) {
|
||||
DEBUG_OUTPUT.println("request handler failed to handle request");
|
||||
DBGWS("request handler failed to handle request\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!handled && _notFoundHandler) {
|
||||
_notFoundHandler();
|
||||
|
Reference in New Issue
Block a user