1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-27 21:16:50 +03:00

Convert ESP8266WebServer* into templatized model (#5982)

* Convert ESP8266WebServer* into templatized model

Supercedes #4912

Refactor the three versions of ESP8266WebServer and *WebServerSecure to a
single templated class. Use "using" to enable old, non-templated names to b
used (so no user changes required to compile or run).

Fixes #4908 and clean up the code base a lot.

Basic tests run (the ones in the example code).

No code changes are required in userland except for setting the SSL
certificates which now use a cleaner "getServer()" accessor and lets the
app use the native BearSSL calls on the WiFiClientSecure object.

@devyte should be proud, it removes virtuals and even has template specialization...

* Fix HTTPUpdate templates and examples

* Fix HTTPUpdateServer library build

Need to remove dot-a linkage since there are no .cpp files in the
directory anymore due to templates.

* Provide backward-compat names for updt template

Allow existing code to use the same well known names for
HTTPUpdateSecure.

* Remove ClientType from all templates, auto-infer

Remove the ClientType template parameter from all objects.  Simplifies
the code and makes it more foolproof.

Add a "using" in each server to define the type of connection returned
by all servers, which is then used in the above templates automatically.

* Can safely include FS.h now that SD/SPIFFS unified

* Move the templates/objects to their own namespaces

* Fix merge issues with untemplated methods

* Address review comments

* Fix mock test, remove warnings inside test dir

Make the simple mock test CI job pass and clean up
any spurious warnings in the test directory.

There still are warnings in the libraries and core, but they
should be addressed in a separate PR.
This commit is contained in:
Earle F. Philhower, III 2019-07-04 01:58:22 -07:00 committed by david gauchard
parent 93a52f923b
commit 7036297920
26 changed files with 291 additions and 601 deletions

View File

@ -31,8 +31,8 @@ const char* update_password = "admin";
const char* ssid = STASSID;
const char* password = STAPSK;
BearSSL::ESP8266WebServerSecure httpServer(443);
ESP8266HTTPUpdateServer httpUpdater;
ESP8266WebServerSecure httpServer(443);
ESP8266HTTPUpdateServerSecure httpUpdater;
static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
@ -106,7 +106,7 @@ void setup()
MDNS.begin(host);
httpServer.setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
httpServer.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();

View File

@ -42,11 +42,21 @@
This example is released into the public domain.
*/
// AXTLS is deprecated, do not use in new code.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServerSecure.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <WiFiServerSecure.h>
#include <WiFiServerSecureAxTLS.h>
#include <WiFiClientSecure.h>
#include <WiFiClientSecureAxTLS.h>
#pragma GCC diagnostic pop
#ifndef STASSID
#define STASSID "your-ssid"
@ -60,8 +70,8 @@ const char* update_password = "admin";
const char* ssid = STASSID;
const char* password = STAPSK;
ESP8266WebServerSecure httpServer(443);
ESP8266HTTPUpdateServer httpUpdater;
axTLS::ESP8266WebServerSecure httpServer(443);
axTLS::ESP8266HTTPUpdateServerSecure httpUpdater;
// The certificate is stored in PMEM
static const uint8_t x509[] PROGMEM = {
@ -176,7 +186,7 @@ void setup() {
MDNS.begin(host);
httpServer.setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
httpServer.getServer().setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();

View File

@ -7,4 +7,4 @@ paragraph=The library accepts HTTP post requests to the /update url, and updates
category=Communication
url=
architectures=esp8266
dot_a_linkage=true
dot_a_linkage=false

View File

@ -6,6 +6,8 @@
#include "StreamString.h"
#include "ESP8266HTTPUpdateServer.h"
namespace esp8266httpupdateserver {
using namespace esp8266webserver;
static const char serverIndex[] PROGMEM =
R"(<html><body><form method='POST' action='' enctype='multipart/form-data'>
@ -16,7 +18,8 @@ static const char serverIndex[] PROGMEM =
static const char successResponse[] PROGMEM =
"<META http-equiv=\"refresh\" content=\"15;URL=/\">Update Success! Rebooting...\n";
ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
template <typename ServerType>
ESP8266HTTPUpdateServerTemplate<ServerType>::ESP8266HTTPUpdateServerTemplate(bool serial_debug)
{
_serial_output = serial_debug;
_server = NULL;
@ -25,7 +28,8 @@ ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
_authenticated = false;
}
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const String& path, const String& username, const String& password)
template <typename ServerType>
void ESP8266HTTPUpdateServerTemplate<ServerType>::setup(ESP8266WebServerTemplate<ServerType> *server, const String& path, const String& username, const String& password)
{
_server = server;
_username = username;
@ -95,10 +99,13 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const String& path
});
}
void ESP8266HTTPUpdateServer::_setUpdaterError()
template <typename ServerType>
void ESP8266HTTPUpdateServerTemplate<ServerType>::_setUpdaterError()
{
if (_serial_output) Update.printError(Serial);
StreamString str;
Update.printError(str);
_updaterError = str.c_str();
}
};

View File

@ -1,29 +1,33 @@
#ifndef __HTTP_UPDATE_SERVER_H
#define __HTTP_UPDATE_SERVER_H
class ESP8266WebServer;
#include <ESP8266WebServer.h>
class ESP8266HTTPUpdateServer
namespace esp8266httpupdateserver {
using namespace esp8266webserver;
template <typename ServerType>
class ESP8266HTTPUpdateServerTemplate
{
public:
ESP8266HTTPUpdateServer(bool serial_debug=false);
ESP8266HTTPUpdateServerTemplate(bool serial_debug=false);
void setup(ESP8266WebServer *server)
void setup(ESP8266WebServerTemplate<ServerType> *server)
{
setup(server, emptyString, emptyString);
}
void setup(ESP8266WebServer *server, const String& path)
void setup(ESP8266WebServerTemplate<ServerType> *server, const String& path)
{
setup(server, path, emptyString, emptyString);
}
void setup(ESP8266WebServer *server, const String& username, const String& password)
void setup(ESP8266WebServerTemplate<ServerType> *server, const String& username, const String& password)
{
setup(server, "/update", username, password);
}
void setup(ESP8266WebServer *server, const String& path, const String& username, const String& password);
void setup(ESP8266WebServerTemplate<ServerType> *server, const String& path, const String& username, const String& password);
void updateCredentials(const String& username, const String& password)
{
@ -36,12 +40,26 @@ class ESP8266HTTPUpdateServer
private:
bool _serial_output;
ESP8266WebServer *_server;
ESP8266WebServerTemplate<ServerType> *_server;
String _username;
String _password;
bool _authenticated;
String _updaterError;
};
};
#include "ESP8266HTTPUpdateServer-impl.h"
using ESP8266HTTPUpdateServer = esp8266httpupdateserver::ESP8266HTTPUpdateServerTemplate<WiFiServer>;
namespace BearSSL {
using ESP8266HTTPUpdateServerSecure = esp8266httpupdateserver::ESP8266HTTPUpdateServerTemplate<WiFiServerSecure>;
};
namespace axTLS {
using ESP8266HTTPUpdateServerSecure = esp8266httpupdateserver::ESP8266HTTPUpdateServerTemplate<WiFiServerSecure>;
};
#endif

View File

@ -128,7 +128,7 @@ void setup(void){
Serial.println("MDNS responder started");
}
server.setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
server.on("/", handleRoot);

View File

@ -165,7 +165,7 @@ void setup(void) {
Serial.println("MDNS responder started");
}
server.setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
server.getServer().setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
server.on("/", handleRoot);

View File

@ -110,7 +110,7 @@ void setup() {
ESP.restart();
}
server.setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
server.on("/",showcredentialpage); //for this simple example, just show a simple page for changing credentials at the root
server.on("/" + change_creds,handlecredentialchange); //handles submission of credentials from the client
server.onNotFound(redirect);

View File

@ -43,7 +43,8 @@ static const char WWW_Authenticate[] PROGMEM = "WWW-Authenticate";
static const char Content_Length[] PROGMEM = "Content-Length";
ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
template <typename ServerType>
ESP8266WebServerTemplate<ServerType>::ESP8266WebServerTemplate(IPAddress addr, int port)
: _server(addr, port)
, _currentMethod(HTTP_ANY)
, _currentVersion(0)
@ -63,7 +64,8 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
{
}
ESP8266WebServer::ESP8266WebServer(int port)
template <typename ServerType>
ESP8266WebServerTemplate<ServerType>::ESP8266WebServerTemplate(int port)
: _server(port)
, _currentMethod(HTTP_ANY)
, _currentVersion(0)
@ -83,36 +85,41 @@ ESP8266WebServer::ESP8266WebServer(int port)
{
}
ESP8266WebServer::~ESP8266WebServer() {
template <typename ServerType>
ESP8266WebServerTemplate<ServerType>::~ESP8266WebServerTemplate() {
_server.close();
if (_currentHeaders)
delete[]_currentHeaders;
RequestHandler* handler = _firstHandler;
RequestHandlerType* handler = _firstHandler;
while (handler) {
RequestHandler* next = handler->next();
RequestHandlerType* next = handler->next();
delete handler;
handler = next;
}
}
void ESP8266WebServer::begin() {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::begin() {
close();
_server.begin();
}
void ESP8266WebServer::begin(uint16_t port) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::begin(uint16_t port) {
close();
_server.begin(port);
}
String ESP8266WebServer::_extractParam(String& authReq,const String& param,const char delimit) const {
template <typename ServerType>
String ESP8266WebServerTemplate<ServerType>::_extractParam(String& authReq,const String& param,const char delimit) const {
int _begin = authReq.indexOf(param);
if (_begin == -1)
return emptyString;
return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length()));
}
bool ESP8266WebServer::authenticate(const char * username, const char * password){
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::authenticate(const char * username, const char * password){
if(hasHeader(FPSTR(AUTHORIZATION_HEADER))) {
String authReq = header(FPSTR(AUTHORIZATION_HEADER));
if(authReq.startsWith(F("Basic"))){
@ -149,7 +156,8 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password
return false;
}
bool ESP8266WebServer::authenticateDigest(const String& username, const String& H1)
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::authenticateDigest(const String& username, const String& H1)
{
if(hasHeader(FPSTR(AUTHORIZATION_HEADER))) {
String authReq = header(FPSTR(AUTHORIZATION_HEADER));
@ -226,7 +234,8 @@ bool ESP8266WebServer::authenticateDigest(const String& username, const String&
return false;
}
String ESP8266WebServer::_getRandomHexString() {
template <typename ServerType>
String ESP8266WebServerTemplate<ServerType>::_getRandomHexString() {
char buffer[33]; // buffer to hold 32 Hex Digit + /0
int i;
for(i = 0; i < 4; i++) {
@ -235,7 +244,8 @@ String ESP8266WebServer::_getRandomHexString() {
return String(buffer);
}
void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) {
if(realm == NULL) {
_srealm = String(F("Login Required"));
} else {
@ -252,23 +262,28 @@ void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* re
send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg);
}
void ESP8266WebServer::on(const String &uri, ESP8266WebServer::THandlerFunction handler) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::on(const String &uri, ESP8266WebServerTemplate<ServerType>::THandlerFunction handler) {
on(uri, HTTP_ANY, handler);
}
void ESP8266WebServer::on(const String &uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::on(const String &uri, HTTPMethod method, ESP8266WebServerTemplate<ServerType>::THandlerFunction fn) {
on(uri, method, fn, _fileUploadHandler);
}
void ESP8266WebServer::on(const String &uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn) {
_addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::on(const String &uri, HTTPMethod method, ESP8266WebServerTemplate<ServerType>::THandlerFunction fn, ESP8266WebServerTemplate<ServerType>::THandlerFunction ufn) {
_addRequestHandler(new FunctionRequestHandler<ServerType>(fn, ufn, uri, method));
}
void ESP8266WebServer::addHandler(RequestHandler* handler) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::addHandler(RequestHandlerType* handler) {
_addRequestHandler(handler);
}
void ESP8266WebServer::_addRequestHandler(RequestHandler* handler) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_addRequestHandler(RequestHandlerType* handler) {
if (!_lastHandler) {
_firstHandler = handler;
_lastHandler = handler;
@ -279,13 +294,15 @@ void ESP8266WebServer::_addRequestHandler(RequestHandler* handler) {
}
}
void ESP8266WebServer::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) {
_addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header));
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) {
_addRequestHandler(new StaticRequestHandler<ServerType>(fs, path, uri, cache_header));
}
void ESP8266WebServer::handleClient() {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::handleClient() {
if (_currentStatus == HC_NONE) {
WiFiClient client = _server.available();
ClientType client = _server.available();
if (!client) {
return;
}
@ -338,7 +355,7 @@ void ESP8266WebServer::handleClient() {
}
if (!keepCurrentClient) {
_currentClient = WiFiClient();
_currentClient = ClientType();
_currentStatus = HC_NONE;
_currentUpload.reset();
}
@ -348,18 +365,21 @@ void ESP8266WebServer::handleClient() {
}
}
void ESP8266WebServer::close() {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::close() {
_server.close();
_currentStatus = HC_NONE;
if(!_headerKeysCount)
collectHeaders(0, 0);
}
void ESP8266WebServer::stop() {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::stop() {
close();
}
void ESP8266WebServer::sendHeader(const String& name, const String& value, bool first) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::sendHeader(const String& name, const String& value, bool first) {
String headerLine = name;
headerLine += F(": ");
headerLine += value;
@ -373,11 +393,13 @@ void ESP8266WebServer::sendHeader(const String& name, const String& value, bool
}
}
void ESP8266WebServer::setContentLength(const size_t contentLength) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::setContentLength(const size_t contentLength) {
_contentLength = contentLength;
}
void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
response = String(F("HTTP/1.")) + String(_currentVersion) + ' ';
response += String(code);
response += ' ';
@ -406,18 +428,20 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co
_responseHeaders = "";
}
void ESP8266WebServer::send(int code, const char* content_type, const String& content) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::send(int code, const char* content_type, const String& content) {
String header;
// Can we asume the following?
//if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET)
// _contentLength = CONTENT_LENGTH_UNKNOWN;
_prepareHeader(header, code, content_type, content.length());
_currentClientWrite(header.c_str(), header.length());
_currentClient.write((const uint8_t *)header.c_str(), header.length());
if(content.length())
sendContent(content);
}
void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::send_P(int code, PGM_P content_type, PGM_P content) {
size_t contentLength = 0;
if (content != NULL) {
@ -428,13 +452,14 @@ void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
char type[64];
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
_prepareHeader(header, code, (const char* )type, contentLength);
_currentClientWrite(header.c_str(), header.length());
_currentClient.write((const uint8_t *)header.c_str(), header.length());
if (contentLength) {
sendContent_P(content);
}
}
void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) {
String header;
char type[64];
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
@ -443,52 +468,58 @@ void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_
sendContent_P(content, contentLength);
}
void ESP8266WebServer::send(int code, char* content_type, const String& content) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::send(int code, char* content_type, const String& content) {
send(code, (const char*)content_type, content);
}
void ESP8266WebServer::send(int code, const String& content_type, const String& content) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::send(int code, const String& content_type, const String& content) {
send(code, (const char*)content_type.c_str(), content);
}
void ESP8266WebServer::sendContent(const String& content) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::sendContent(const String& content) {
const char * footer = "\r\n";
size_t len = content.length();
if(_chunked) {
char chunkSize[11];
sprintf(chunkSize, "%zx\r\n", len);
_currentClientWrite(chunkSize, strlen(chunkSize));
_currentClient.write((const uint8_t *)chunkSize, strlen(chunkSize));
}
_currentClientWrite(content.c_str(), len);
_currentClient.write((const uint8_t *)content.c_str(), len);
if(_chunked){
_currentClient.write(footer, 2);
_currentClient.write((const uint8_t *)footer, 2);
if (len == 0) {
_chunked = false;
}
}
}
void ESP8266WebServer::sendContent_P(PGM_P content) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::sendContent_P(PGM_P content) {
sendContent_P(content, strlen_P(content));
}
void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::sendContent_P(PGM_P content, size_t size) {
const char * footer = "\r\n";
if(_chunked) {
char chunkSize[11];
sprintf(chunkSize, "%zx\r\n", size);
_currentClientWrite(chunkSize, strlen(chunkSize));
_currentClient.write((const uint8_t *)chunkSize, strlen(chunkSize));
}
_currentClientWrite_P(content, size);
_currentClient.write_P(content, size);
if(_chunked){
_currentClient.write(footer, 2);
_currentClient.write((const uint8_t *)footer, 2);
if (size == 0) {
_chunked = false;
}
}
}
String ESP8266WebServer::credentialHash(const String& username, const String& realm, const String& password)
template <typename ServerType>
String ESP8266WebServerTemplate<ServerType>::credentialHash(const String& username, const String& realm, const String& password)
{
MD5Builder md5;
md5.begin();
@ -497,7 +528,8 @@ String ESP8266WebServer::credentialHash(const String& username, const String& re
return md5.toString();
}
void ESP8266WebServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType)
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType)
{
using namespace mime;
setContentLength(fileSize);
@ -510,7 +542,8 @@ void ESP8266WebServer::_streamFileCore(const size_t fileSize, const String & fil
}
const String& ESP8266WebServer::arg(String name) const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::arg(String name) const {
for (int j = 0; j < _postArgsLen; ++j) {
if ( _postArgs[j].key == name )
return _postArgs[j].value;
@ -522,23 +555,27 @@ const String& ESP8266WebServer::arg(String name) const {
return emptyString;
}
const String& ESP8266WebServer::arg(int i) const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::arg(int i) const {
if (i >= 0 && i < _currentArgCount)
return _currentArgs[i].value;
return emptyString;
}
const String& ESP8266WebServer::argName(int i) const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::argName(int i) const {
if (i >= 0 && i < _currentArgCount)
return _currentArgs[i].key;
return emptyString;
}
int ESP8266WebServer::args() const {
template <typename ServerType>
int ESP8266WebServerTemplate<ServerType>::args() const {
return _currentArgCount;
}
bool ESP8266WebServer::hasArg(const String& name) const {
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::hasArg(const String& name) const {
for (int j = 0; j < _postArgsLen; ++j) {
if (_postArgs[j].key == name)
return true;
@ -551,7 +588,8 @@ bool ESP8266WebServer::hasArg(const String& name) const {
}
const String& ESP8266WebServer::header(String name) const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::header(String name) const {
for (int i = 0; i < _headerKeysCount; ++i) {
if (_currentHeaders[i].key.equalsIgnoreCase(name))
return _currentHeaders[i].value;
@ -559,7 +597,8 @@ const String& ESP8266WebServer::header(String name) const {
return emptyString;
}
void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
_headerKeysCount = headerKeysCount + 1;
if (_currentHeaders)
delete[]_currentHeaders;
@ -570,23 +609,27 @@ void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t hea
}
}
const String& ESP8266WebServer::header(int i) const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::header(int i) const {
if (i < _headerKeysCount)
return _currentHeaders[i].value;
return emptyString;
}
const String& ESP8266WebServer::headerName(int i) const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::headerName(int i) const {
if (i < _headerKeysCount)
return _currentHeaders[i].key;
return emptyString;
}
int ESP8266WebServer::headers() const {
template <typename ServerType>
int ESP8266WebServerTemplate<ServerType>::headers() const {
return _headerKeysCount;
}
bool ESP8266WebServer::hasHeader(String name) const {
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::hasHeader(String name) const {
for (int i = 0; i < _headerKeysCount; ++i) {
if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0))
return true;
@ -594,19 +637,23 @@ bool ESP8266WebServer::hasHeader(String name) const {
return false;
}
const String& ESP8266WebServer::hostHeader() const {
template <typename ServerType>
const String& ESP8266WebServerTemplate<ServerType>::hostHeader() const {
return _hostHeader;
}
void ESP8266WebServer::onFileUpload(THandlerFunction fn) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::onFileUpload(THandlerFunction fn) {
_fileUploadHandler = fn;
}
void ESP8266WebServer::onNotFound(THandlerFunction fn) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::onNotFound(THandlerFunction fn) {
_notFoundHandler = fn;
}
void ESP8266WebServer::_handleRequest() {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_handleRequest() {
bool handled = false;
if (!_currentHandler){
#ifdef DEBUG_ESP_HTTP_SERVER
@ -637,13 +684,15 @@ void ESP8266WebServer::_handleRequest() {
}
void ESP8266WebServer::_finalizeResponse() {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_finalizeResponse() {
if (_chunked) {
sendContent(emptyString);
}
}
const String ESP8266WebServer::responseCodeToString(const int code) {
template <typename ServerType>
const String ESP8266WebServerTemplate<ServerType>::responseCodeToString(const int code) {
switch (code) {
case 100: return F("Continue");
case 101: return F("Switching Protocols");

View File

@ -27,6 +27,8 @@
#include <functional>
#include <memory>
#include <ESP8266WiFi.h>
#include <FS.h>
#include "detail/mimetable.h"
enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
@ -48,8 +50,6 @@ enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
#define CONTENT_LENGTH_NOT_SET ((size_t) -2)
class ESP8266WebServer;
typedef struct {
HTTPUploadStatus status;
String filename;
@ -61,24 +61,29 @@ typedef struct {
uint8_t buf[HTTP_UPLOAD_BUFLEN];
} HTTPUpload;
namespace esp8266webserver {
template<typename ServerType>
class ESP8266WebServerTemplate;
#include "detail/RequestHandler.h"
namespace fs {
class FS;
}
class ESP8266WebServer
template<typename ServerType>
class ESP8266WebServerTemplate
{
public:
ESP8266WebServer(IPAddress addr, int port = 80);
ESP8266WebServer(int port = 80);
virtual ~ESP8266WebServer();
ESP8266WebServerTemplate(IPAddress addr, int port = 80);
ESP8266WebServerTemplate(int port = 80);
~ESP8266WebServerTemplate();
virtual void begin();
virtual void begin(uint16_t port);
virtual void handleClient();
using ClientType = typename ServerType::ClientType;
using RequestHandlerType = RequestHandler<ServerType>;
using WebServerType = ESP8266WebServerTemplate<ServerType>;
virtual void close();
void begin();
void begin(uint16_t port);
void handleClient();
void close();
void stop();
bool authenticate(const char * username, const char * password);
@ -89,16 +94,19 @@ public:
void on(const String &uri, THandlerFunction handler);
void on(const String &uri, HTTPMethod method, THandlerFunction fn);
void on(const String &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn);
void addHandler(RequestHandler* handler);
void addHandler(RequestHandlerType* handler);
void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL );
void onNotFound(THandlerFunction fn); //called when handler is not assigned
void onFileUpload(THandlerFunction fn); //handle file uploads
const String& uri() const { return _currentUri; }
HTTPMethod method() const { return _currentMethod; }
virtual WiFiClient client() { return _currentClient; }
ClientType client() { return _currentClient; }
HTTPUpload& upload() { return *_currentUpload; }
// Allows setting server options (i.e. SSL keys) by the instantiator
ServerType &getServer() { return _server; }
const String& arg(String name) const; // get request argument value by name
const String& arg(int i) const; // get request argument value by number
const String& argName(int i) const; // get request argument name by number
@ -141,18 +149,16 @@ public:
static const String responseCodeToString(const int code);
protected:
virtual size_t _currentClientWrite(const char* b, size_t l) { return _currentClient.write( b, l ); }
virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
void _addRequestHandler(RequestHandler* handler);
void _addRequestHandler(RequestHandlerType* handler);
void _handleRequest();
void _finalizeResponse();
bool _parseRequest(WiFiClient& client);
bool _parseRequest(ClientType& client);
void _parseArguments(const String& data);
int _parseArgumentsPrivate(const String& data, std::function<void(String&,String&,const String&,int,int,int,int)> handler);
bool _parseForm(WiFiClient& client, const String& boundary, uint32_t len);
bool _parseForm(ClientType& client, const String& boundary, uint32_t len);
bool _parseFormUploadAborted();
void _uploadWriteByte(uint8_t b);
uint8_t _uploadReadByte(WiFiClient& client);
uint8_t _uploadReadByte(ClientType& client);
void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);
bool _collectHeader(const char* headerName, const char* headerValue);
@ -167,18 +173,17 @@ protected:
String value;
};
WiFiServer _server;
WiFiClient _currentClient;
ServerType _server;
ClientType _currentClient;
HTTPMethod _currentMethod;
String _currentUri;
uint8_t _currentVersion;
HTTPClientStatus _currentStatus;
unsigned long _statusChange;
RequestHandler* _currentHandler;
RequestHandler* _firstHandler;
RequestHandler* _lastHandler;
RequestHandlerType* _currentHandler;
RequestHandlerType* _firstHandler;
RequestHandlerType* _lastHandler;
THandlerFunction _notFoundHandler;
THandlerFunction _fileUploadHandler;
@ -204,4 +209,13 @@ protected:
};
#include "ESP8266WebServer-impl.h"
#include "Parsing-impl.h"
};
using ESP8266WebServer = esp8266webserver::ESP8266WebServerTemplate<WiFiServer>;
#endif //ESP8266WEBSERVER_H

View File

@ -19,7 +19,13 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <ESP8266WebServer.h>
#include <WiFiClientSecure.h>
//#include "ESP8266WebServerSecureAxTLS.h"
#include "ESP8266WebServerSecureBearSSL.h"
namespace axTLS {
using ESP8266WebServerSecure = esp8266webserver::ESP8266WebServerTemplate<WiFiServerSecure>;
};
namespace BearSSL {
using ESP8266WebServerSecure = esp8266webserver::ESP8266WebServerTemplate<WiFiServerSecure>;
};

View File

@ -1,157 +0,0 @@
/*
ESP8266WebServerSecure.cpp - Dead simple HTTPS web-server.
Supports only one simultaneous client, knows how to handle GET and POST.
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
*/
#include <Arduino.h>
#include <libb64/cencode.h>
#include "WiFiServer.h"
#include "WiFiClient.h"
#include "ESP8266WebServerSecureAxTLS.h"
//#define DEBUG_ESP_HTTP_SERVER
#ifdef DEBUG_ESP_PORT
#define DEBUG_OUTPUT DEBUG_ESP_PORT
#else
#define DEBUG_OUTPUT Serial
#endif
namespace axTLS {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
ESP8266WebServerSecure::ESP8266WebServerSecure(IPAddress addr, int port)
: _serverSecure(addr, port)
{
}
ESP8266WebServerSecure::ESP8266WebServerSecure(int port)
: _serverSecure(port)
{
}
#pragma GCC diagnostic pop
void ESP8266WebServerSecure::setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
{
_serverSecure.setServerKeyAndCert_P(key, keyLen, cert, certLen);
}
void ESP8266WebServerSecure::setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
{
_serverSecure.setServerKeyAndCert(key, keyLen, cert, certLen);
}
ESP8266WebServerSecure::~ESP8266WebServerSecure() {
// Nothing to do here.
// Base class's destructor will be called to clean up itself
}
// We need to basically cut-n-paste these from WebServer because of the problem
// of object slicing. The class uses assignment operators like "WiFiClient x=y;"
// When this happens, even if "y" is a WiFiClientSecure, the main class is
// already compiled down into code which will only copy the WiFiClient superclass
// and not the extra bits for our own class (since when it was compiled it needed
// to know the size of memory to allocate on the stack for this local variable
// there's not realy anything else it could do).
void ESP8266WebServerSecure::begin() {
_currentStatus = HC_NONE;
_serverSecure.begin();
if(!_headerKeysCount)
collectHeaders(0, 0);
}
void ESP8266WebServerSecure::handleClient() {
if (_currentStatus == HC_NONE) {
WiFiClientSecure client = _serverSecure.available();
if (!client) {
return;
}
#ifdef DEBUG_ESP_HTTP_SERVER
DEBUG_OUTPUT.println("New secure client");
#endif
_currentClientSecure = client;
_currentStatus = HC_WAIT_READ;
_statusChange = millis();
}
bool keepCurrentClient = false;
bool callYield = false;
if (_currentClientSecure.connected()) {
switch (_currentStatus) {
case HC_NONE:
// No-op to avoid C++ compiler warning
break;
case HC_WAIT_READ:
// Wait for data from client to become available
if (_currentClientSecure.available()) {
if (_parseRequest(_currentClientSecure)) {
_currentClientSecure.setTimeout(HTTP_MAX_SEND_WAIT);
_contentLength = CONTENT_LENGTH_NOT_SET;
_handleRequest();
if (_currentClientSecure.connected()) {
_currentStatus = HC_WAIT_CLOSE;
_statusChange = millis();
keepCurrentClient = true;
}
}
} else { // !_currentClient.available()
if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) {
keepCurrentClient = true;
}
callYield = true;
}
break;
case HC_WAIT_CLOSE:
// Wait for client to close the connection
if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) {
keepCurrentClient = true;
callYield = true;
}
}
}
if (!keepCurrentClient) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
_currentClientSecure = WiFiClientSecure();
#pragma GCC diagnostic pop
_currentStatus = HC_NONE;
_currentUpload.reset();
}
if (callYield) {
yield();
}
}
void ESP8266WebServerSecure::close() {
_currentClientSecure.stop();
_serverSecure.close();
}
};

View File

@ -1,65 +0,0 @@
/*
ESP8266WebServerSecure.h - Dead simple HTTPS web-server.
Supports only one simultaneous client, knows how to handle GET and POST.
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ESP8266WEBSERVERSECURE_H
#define ESP8266WEBSERVERSECURE_H
#include <ESP8266WebServer.h>
#include <WiFiServerSecureAxTLS.h>
#include <WiFiClientSecureAxTLS.h>
namespace axTLS {
class ESP8266WebServerSecure : public ESP8266WebServer
{
public:
ESP8266WebServerSecure(IPAddress addr, int port = 443);
ESP8266WebServerSecure(int port = 443);
virtual ~ESP8266WebServerSecure();
void setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
void setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
WiFiClient client() override { return _currentClientSecure; }
void begin() override;
void handleClient() override;
void close() override;
template<typename T>
size_t streamFile(T &file, const String& contentType) {
_streamFileCore(file.size(), file.name(), contentType);
return _currentClientSecure.write(file);
}
private:
size_t _currentClientWrite (const char *bytes, size_t len) override { return _currentClientSecure.write((const uint8_t *)bytes, len); }
size_t _currentClientWrite_P (PGM_P bytes, size_t len) override { return _currentClientSecure.write_P(bytes, len); }
protected:
WiFiServerSecure _serverSecure;
WiFiClientSecure _currentClientSecure;
};
};
#endif //ESP8266WEBSERVERSECURE_H

View File

@ -1,165 +0,0 @@
/*
ESP8266WebServerSecure.cpp - Dead simple HTTPS web-server.
Supports only one simultaneous client, knows how to handle GET and POST.
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
*/
#include <Arduino.h>
#include <libb64/cencode.h>
#include "WiFiServer.h"
#include "WiFiClient.h"
#include "ESP8266WebServerSecureBearSSL.h"
//#define DEBUG_ESP_HTTP_SERVER
#ifdef DEBUG_ESP_PORT
#define DEBUG_OUTPUT DEBUG_ESP_PORT
#else
#define DEBUG_OUTPUT Serial
#endif
namespace BearSSL {
ESP8266WebServerSecure::ESP8266WebServerSecure(IPAddress addr, int port)
: _serverSecure(addr, port)
{
}
ESP8266WebServerSecure::ESP8266WebServerSecure(int port)
: _serverSecure(port)
{
}
void ESP8266WebServerSecure::setRSACert(const X509List *chain, const PrivateKey *sk)
{
_serverSecure.setRSACert(chain, sk);
}
void ESP8266WebServerSecure::setECCert(const X509List *chain, unsigned cert_issuer_key_type, const PrivateKey *sk)
{
_serverSecure.setECCert(chain, cert_issuer_key_type, sk);
}
void ESP8266WebServerSecure::setBufferSizes(int recv, int xmit)
{
_serverSecure.setBufferSizes(recv, xmit);
}
ESP8266WebServerSecure::~ESP8266WebServerSecure() {
// Nothing to do here.
// Base class's destructor will be called to clean up itself
}
// We need to basically cut-n-paste these from WebServer because of the problem
// of object slicing. The class uses assignment operators like "WiFiClient x=y;"
// When this happens, even if "y" is a WiFiClientSecure, the main class is
// already compiled down into code which will only copy the WiFiClient superclass
// and not the extra bits for our own class (since when it was compiled it needed
// to know the size of memory to allocate on the stack for this local variable
// there's not realy anything else it could do).
void ESP8266WebServerSecure::begin() {
_currentStatus = HC_NONE;
_serverSecure.begin();
if(!_headerKeysCount)
collectHeaders(0, 0);
}
void ESP8266WebServerSecure::handleClient() {
if (_currentStatus == HC_NONE) {
WiFiClientSecure client = _serverSecure.available();
if (!client) {
return;
}
#ifdef DEBUG_ESP_HTTP_SERVER
DEBUG_OUTPUT.println("New secure client");
#endif
_currentClientSecure = client;
_currentStatus = HC_WAIT_READ;
_statusChange = millis();
}
bool keepCurrentClient = false;
bool callYield = false;
if (_currentClientSecure.connected()) {
switch (_currentStatus) {
case HC_NONE:
// No-op to avoid C++ compiler warning
break;
case HC_WAIT_READ:
// Wait for data from client to become available
if (_currentClientSecure.available()) {
if (_parseRequest(_currentClientSecure)) {
_currentClientSecure.setTimeout(HTTP_MAX_SEND_WAIT);
_contentLength = CONTENT_LENGTH_NOT_SET;
_handleRequest();
if (_currentClientSecure.connected()) {
_currentStatus = HC_WAIT_CLOSE;
_statusChange = millis();
keepCurrentClient = true;
}
}
} else { // !_currentClient.available()
if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) {
keepCurrentClient = true;
}
callYield = true;
}
break;
case HC_WAIT_CLOSE:
// Wait for client to close the connection
if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) {
keepCurrentClient = true;
callYield = true;
}
}
}
if (!keepCurrentClient) {
_currentClientSecure = WiFiClientSecure();
_currentStatus = HC_NONE;
_currentUpload.reset();
}
if (callYield) {
yield();
}
}
void ESP8266WebServerSecure::close() {
_currentClientSecure.flush();
_currentClientSecure.stop();
_serverSecure.close();
}
void ESP8266WebServerSecure::setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen) {
_serverSecure.setServerKeyAndCert_P(key, keyLen, cert, certLen);
}
void ESP8266WebServerSecure::setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
{
_serverSecure.setServerKeyAndCert(key, keyLen, cert, certLen);
}
};

View File

@ -1,69 +0,0 @@
/*
ESP8266WebServerSecure.h - Dead simple HTTPS web-server.
Supports only one simultaneous client, knows how to handle GET and POST.
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ESP8266WEBSERVERBEARSSL_H
#define ESP8266WEBSERVERBEARSSL_H
#include <ESP8266WebServer.h>
#include <BearSSLHelpers.h>
#include <WiFiServerSecureBearSSL.h>
namespace BearSSL {
class ESP8266WebServerSecure : public ESP8266WebServer
{
public:
ESP8266WebServerSecure(IPAddress addr, int port = 443);
ESP8266WebServerSecure(int port = 443);
virtual ~ESP8266WebServerSecure();
void setBufferSizes(int recv, int xmit);
void setRSACert(const X509List *chain, const PrivateKey *sk);
void setECCert(const X509List *chain, unsigned cert_issuer_key_type, const PrivateKey *sk);
WiFiClient client() override { return _currentClientSecure; }
void begin() override;
void handleClient() override;
void close() override;
template<typename T>
size_t streamFile(T &file, const String& contentType) {
_streamFileCore(file.size(), file.name(), contentType);
return _currentClientSecure.write(file);
}
// AXTLS Compatibility
void setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
void setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
private:
size_t _currentClientWrite (const char *bytes, size_t len) override { return _currentClientSecure.write((const uint8_t *)bytes, len); }
size_t _currentClientWrite_P (PGM_P bytes, size_t len) override { return _currentClientSecure.write_P(bytes, len); }
protected:
WiFiServerSecure _serverSecure;
WiFiClientSecure _currentClientSecure;
};
};
#endif //ESP8266WEBSERVERSECURE_H

View File

@ -39,7 +39,8 @@
static const char Content_Type[] PROGMEM = "Content-Type";
static const char filename[] PROGMEM = "filename";
static bool readBytesWithTimeout(WiFiClient& client, size_t maxLength, String& data, int timeout_ms)
template <typename ServerType>
static bool readBytesWithTimeout(typename ServerType::ClientType& client, size_t maxLength, String& data, int timeout_ms)
{
if (!data.reserve(maxLength + 1))
return false;
@ -59,7 +60,8 @@ static bool readBytesWithTimeout(WiFiClient& client, size_t maxLength, String& d
return data.length() == maxLength;
}
bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
// Read the first line of HTTP request
String req = client.readStringUntil('\r');
#ifdef DEBUG_ESP_HTTP_SERVER
@ -120,7 +122,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
#endif
//attach handler
RequestHandler* handler;
RequestHandlerType* handler;
for (handler = _firstHandler; handler; handler = handler->next()) {
if (handler->canHandle(_currentMethod, _currentUri))
break;
@ -179,7 +181,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
String plainBuf;
if ( !isForm
&& // read content into plainBuf
( !readBytesWithTimeout(client, contentLength, plainBuf, HTTP_MAX_POST_WAIT)
( !readBytesWithTimeout<ServerType>(client, contentLength, plainBuf, HTTP_MAX_POST_WAIT)
|| (plainBuf.length() < contentLength)
)
)
@ -258,7 +260,8 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
return true;
}
bool ESP8266WebServer::_collectHeader(const char* headerName, const char* headerValue) {
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::_collectHeader(const char* headerName, const char* headerValue) {
for (int i = 0; i < _headerKeysCount; i++) {
if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
_currentHeaders[i].value=headerValue;
@ -268,13 +271,14 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header
return false;
}
template <typename ServerType>
struct storeArgHandler
{
void operator() (String& key, String& value, const String& data, int equal_index, int pos, int key_end_pos, int next_index)
{
key = ESP8266WebServer::urlDecode(data.substring(pos, key_end_pos));
key = ESP8266WebServerTemplate<ServerType>::urlDecode(data.substring(pos, key_end_pos));
if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1)))
value = ESP8266WebServer::urlDecode(data.substring(equal_index + 1, next_index));
value = ESP8266WebServerTemplate<ServerType>::urlDecode(data.substring(equal_index + 1, next_index));
}
};
@ -286,7 +290,8 @@ struct nullArgHandler
}
};
void ESP8266WebServer::_parseArguments(const String& data) {
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_parseArguments(const String& data) {
if (_currentArgs)
delete[] _currentArgs;
@ -295,10 +300,11 @@ void ESP8266WebServer::_parseArguments(const String& data) {
// allocate one more, this is needed because {"plain": plainBuf} is always added
_currentArgs = new RequestArgument[_currentArgCount + 1];
(void)_parseArgumentsPrivate(data, storeArgHandler());
(void)_parseArgumentsPrivate(data, storeArgHandler<ServerType>());
}
int ESP8266WebServer::_parseArgumentsPrivate(const String& data, std::function<void(String&,String&,const String&,int,int,int,int)> handler) {
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: ");
@ -349,7 +355,8 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, std::function<v
return arg_total;
}
void ESP8266WebServer::_uploadWriteByte(uint8_t b){
template <typename ServerType>
void ESP8266WebServerTemplate<ServerType>::_uploadWriteByte(uint8_t b){
if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN){
if(_currentHandler && _currentHandler->canUpload(_currentUri))
_currentHandler->upload(*this, _currentUri, *_currentUpload);
@ -359,7 +366,8 @@ void ESP8266WebServer::_uploadWriteByte(uint8_t b){
_currentUpload->buf[_currentUpload->currentSize++] = b;
}
uint8_t ESP8266WebServer::_uploadReadByte(WiFiClient& client){
template <typename ServerType>
uint8_t ESP8266WebServerTemplate<ServerType>::_uploadReadByte(ClientType& client){
int res = client.read();
if(res == -1){
while(!client.available() && client.connected())
@ -369,7 +377,8 @@ uint8_t ESP8266WebServer::_uploadReadByte(WiFiClient& client){
return (uint8_t)res;
}
bool ESP8266WebServer::_parseForm(WiFiClient& client, const String& boundary, uint32_t len){
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: ");
@ -586,7 +595,8 @@ readfile:
return false;
}
String ESP8266WebServer::urlDecode(const String& text)
template <typename ServerType>
String ESP8266WebServerTemplate<ServerType>::urlDecode(const String& text)
{
String decoded = "";
char temp[] = "0x00";
@ -617,7 +627,8 @@ String ESP8266WebServer::urlDecode(const String& text)
return decoded;
}
bool ESP8266WebServer::_parseFormUploadAborted(){
template <typename ServerType>
bool ESP8266WebServerTemplate<ServerType>::_parseFormUploadAborted(){
_currentUpload->status = UPLOAD_FILE_ABORTED;
if(_currentHandler && _currentHandler->canUpload(_currentUri))
_currentHandler->upload(*this, _currentUri, *_currentUpload);

View File

@ -1,19 +1,23 @@
#ifndef REQUESTHANDLER_H
#define REQUESTHANDLER_H
#include <ESP8266WebServer.h>
template<typename ServerType>
class RequestHandler {
using WebServerType = ESP8266WebServerTemplate<ServerType>;
public:
virtual ~RequestHandler() { }
virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; }
virtual bool canUpload(String uri) { (void) uri; return false; }
virtual bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) { (void) server; (void) requestMethod; (void) requestUri; return false; }
virtual void upload(ESP8266WebServer& server, String requestUri, HTTPUpload& upload) { (void) server; (void) requestUri; (void) upload; }
virtual bool handle(WebServerType& server, HTTPMethod requestMethod, String requestUri) { (void) server; (void) requestMethod; (void) requestUri; return false; }
virtual void upload(WebServerType& server, String requestUri, HTTPUpload& upload) { (void) server; (void) requestUri; (void) upload; }
RequestHandler* next() { return _next; }
void next(RequestHandler* r) { _next = r; }
RequestHandler<ServerType>* next() { return _next; }
void next(RequestHandler<ServerType>* r) { _next = r; }
private:
RequestHandler* _next = nullptr;
RequestHandler<ServerType>* _next = nullptr;
};
#endif //REQUESTHANDLER_H

View File

@ -1,15 +1,18 @@
#ifndef REQUESTHANDLERSIMPL_H
#define REQUESTHANDLERSIMPL_H
#include <ESP8266WebServer.h>
#include "RequestHandler.h"
#include "mimetable.h"
#include "WString.h"
using namespace mime;
class FunctionRequestHandler : public RequestHandler {
template<typename ServerType>
class FunctionRequestHandler : public RequestHandler<ServerType> {
using WebServerType = ESP8266WebServerTemplate<ServerType>;
public:
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn, const String &uri, HTTPMethod method)
FunctionRequestHandler(typename WebServerType::THandlerFunction fn, typename WebServerType::THandlerFunction ufn, const String &uri, HTTPMethod method)
: _fn(fn)
, _ufn(ufn)
, _uri(uri)
@ -34,7 +37,7 @@ public:
return true;
}
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
bool handle(WebServerType& server, HTTPMethod requestMethod, String requestUri) override {
(void) server;
if (!canHandle(requestMethod, requestUri))
return false;
@ -43,7 +46,7 @@ public:
return true;
}
void upload(ESP8266WebServer& server, String requestUri, HTTPUpload& upload) override {
void upload(WebServerType& server, String requestUri, HTTPUpload& upload) override {
(void) server;
(void) upload;
if (canUpload(requestUri))
@ -51,13 +54,15 @@ public:
}
protected:
ESP8266WebServer::THandlerFunction _fn;
ESP8266WebServer::THandlerFunction _ufn;
typename WebServerType::THandlerFunction _fn;
typename WebServerType::THandlerFunction _ufn;
String _uri;
HTTPMethod _method;
};
class StaticRequestHandler : public RequestHandler {
template<typename ServerType>
class StaticRequestHandler : public RequestHandler<ServerType> {
using WebServerType = ESP8266WebServerTemplate<ServerType>;
public:
StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header)
: _fs(fs)
@ -80,7 +85,7 @@ public:
return true;
}
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
bool handle(WebServerType& server, HTTPMethod requestMethod, String requestUri) override {
if (!canHandle(requestMethod, requestUri))
return false;

View File

@ -62,6 +62,7 @@ public:
void stop();
using Print::write;
using ClientType = WiFiClient;
protected:
long _accept(tcp_pcb* newpcb, long err);

View File

@ -34,6 +34,8 @@ public:
void setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
virtual ~WiFiServerSecure() {}
WiFiClientSecure available(uint8_t* status = NULL);
using ClientType = WiFiClientSecure;
private:
bool usePMEM = false;
const uint8_t *rsakey = nullptr;

View File

@ -62,6 +62,8 @@ class WiFiServerSecure : public WiFiServer {
void setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
void setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
using ClientType = WiFiClientSecure;
private:
const X509List *_chain = nullptr;
unsigned _cert_issuer_key_type = 0;

View File

@ -260,8 +260,6 @@ ARDUINO_LIBS := \
OPT_ARDUINO_LIBS ?= $(addprefix ../../libraries/,\
$(addprefix ESP8266WebServer/src/,\
ESP8266WebServer.cpp \
Parsing.cpp \
detail/mimetable.cpp \
) \
$(addprefix ESP8266mDNS/src/,\

View File

@ -94,6 +94,7 @@ uint32_t EspClass::getChipId()
bool EspClass::checkFlashConfig(bool needsEquals)
{
(void) needsEquals;
return true;
}
@ -143,6 +144,7 @@ void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag) {
bool EspClass::flashEraseSector(uint32_t sector)
{
(void) sector;
return true;
}
@ -153,6 +155,7 @@ FlashMode_t EspClass::getFlashChipMode()
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
{
(void) byte;
return FM_DOUT;
}

View File

@ -255,6 +255,7 @@ uart_tx_free(uart_t* uart)
void
uart_wait_tx_empty(uart_t* uart)
{
(void) uart;
}
void
@ -291,6 +292,8 @@ uart_get_baudrate(uart_t* uart)
uart_t*
uart_init(int uart_nr, int baudrate, int config, int mode, int tx_pin, size_t rx_size)
{
(void) config;
(void) tx_pin;
uart_t* uart = (uart_t*) malloc(sizeof(uart_t));
if(uart == NULL)
return NULL;
@ -361,16 +364,23 @@ uart_uninit(uart_t* uart)
void
uart_swap(uart_t* uart, int tx_pin)
{
(void) uart;
(void) tx_pin;
}
void
uart_set_tx(uart_t* uart, int tx_pin)
{
(void) uart;
(void) tx_pin;
}
void
uart_set_pins(uart_t* uart, int tx, int rx)
{
(void) uart;
(void) tx;
(void) rx;
}
bool
@ -405,6 +415,7 @@ uart_has_overrun(uart_t* uart)
bool
uart_has_rx_error(uart_t* uart)
{
(void) uart;
return false;
}
@ -423,11 +434,13 @@ uart_get_debug()
void
uart_start_detect_baudrate(int uart_nr)
{
(void) uart_nr;
}
int
uart_detect_baudrate(int uart_nr)
{
(void) uart_nr;
return 115200;
}

View File

@ -77,6 +77,7 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
// Filling server information
servaddr.sin_family = AF_INET;
//servaddr.sin_addr.s_addr = global_ipv4_netfmt?: dstaddr;
(void) dstaddr;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(mockport);
@ -153,6 +154,7 @@ size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t&
size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
{
(void) sock;
if (usersize > CCBUFSIZE)
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
@ -184,6 +186,7 @@ size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccin
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port)
{
(void) timeout_ms;
// Filling server information
struct sockaddr_in peer;
peer.sin_family = AF_INET;

View File

@ -23,7 +23,7 @@
class SDFSMock {
public:
SDFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString) { }
SDFSMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString) { (void)fs_size; (void)fs_block; (void)fs_page; (void)storage; }
void reset() { }
~SDFSMock() { }
};