Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

Latest commit

 

History

History
1061 lines (778 loc) · 40.5 KB

README.md

File metadata and controls

1061 lines (778 loc) · 40.5 KB

HTTPS_Server_Generic Library

arduino-library-badge GitHub release contributions welcome GitHub issues

Donate to my libraries using BuyMeACoffee



Table of contents



Why do we need this HTTPS_Server_Generic library

Features

This library is based on, modified from:

  1. Frank Hessel's esp32_https_server
  2. Khoi Hoang's ESP32_HTTPS_Server

to apply the HTTPS Server feature of the powerful esp32_https_server into other ESP32 boards, such as WT32_ETH01 (ESP32 + LwIP LAN8720), (ESP32 + LwIP W5500), (ESP32 + LwIP W6100) and (ESP32 + LwIP ENC28J60) Ethernet.

In the future, this library will support powerful-enough boards using LwIP WiFi/Ethernet, such as ESP8266, Portenta_H7, RP2040W, Teensy 4.1, etc.

The library provides these following features:

  • Providing support for HTTP, HTTPS or both at the same time
  • Handling requests in callback functions that can be bound to URLs, like for example in Express or Servlets.
  • Abstraction of handling the HTTP stuff and providing a simple API for it, eg. to access parameters, headers, HTTP Basic Auth etc.
  • Using middleware functions as proxy to every request to perform central tasks like authentication or logging.
  • Make use of the built-in encryption of the ESP32-based boards for HTTPS.
  • Handle multiple clients in parallel (max. 3-4 TLS clients due to memory limits).
  • Usage of Connection: keep-alive and SSL session reuse to reduce the overhead of SSL handshakes and speed up data transfer.

Currently Supported Boards

1. ESP32/S2/S3/C3 using WiFi

  1. ESP32 (ESP32-DEV, etc.)

2. ESP32 using LwIP ENC28J60, W5500, W6100 or LAN8720

  1. ESP32 (ESP32-DEV, etc.)

3. WT32_ETH01 using ESP32-based boards and LAN8720 Ethernet

4. ESP32S3 using LwIP W5500, W6100 or ENC28J60

  1. ESP32-S3 (ESP32S3_DEV, ESP32_S3_BOX, UM TINYS3, UM PROS3, UM FEATHERS3, etc.)

5. ESP32S2 using LwIP W5500, W6100 or ENC28J60

  1. ESP32-S2 (ESP32S2_DEV, ESP32-S2 Saola, AI-Thinker ESP-12K, etc.)

6. ESP32C3 using LwIP W5500, W6100 or ENC28J60

  1. ESP32-C3 (ESP32C3_DEV, etc.)

ESP32S3_DEV

ESP32S2_DEV

ESP32C3_DEV


W6100

FULL_DUPLEX, 100Mbps


W5500

FULL_DUPLEX, 100Mbps


ENC28J60

FULL_DUPLEX, 10Mbps



Prerequisites

  1. Arduino IDE 1.8.19+ for Arduino. GitHub release
  2. ESP32 Core 2.0.5+ for ESP32-based boards. ESP32 Latest Core Latest release
  3. Functional-Vlpp library v1.0.2+ to use server's lambda function. To install. check arduino-library-badge
  4. ArduinoJson library v5.13.5- to use REST-API examples. To install, check arduino-library-badge
  5. WebServer_WT32_ETH01 v1.5.1+ for ESP32-based WT32_ETH01 using either ESP32 core v2.0.0+ or v1.0.6-. GitHub release
  6. WebServer_ESP32_ENC library v1.5.1+ if necessary to use ESP32 boards using LwIP ENC28J60 Ethernet. To install, check arduino-library-badge
  7. WebServer_ESP32_W5500 library v1.5.2+ if necessary to use ESP32 boards using LwIP W5500 Ethernet. To install, check arduino-library-badge
  8. WebServer_ESP32_SC_ENC library v1.2.0+ if necessary to use ESP32_S2/S3/C3 boards using LwIP ENC28J60 Ethernet. To install, check arduino-library-badge
  9. WebServer_ESP32_SC_W5500 library v1.2.1+ if necessary to use ESP32_S2/S3/C3 boards using LwIP W5500 Ethernet. To install, check arduino-library-badge
  10. WebServer_ESP32_W6100 library v1.5.2+ if necessary to use ESP32 boards using LwIP W6100 Ethernet. To install, check arduino-library-badge
  11. WebServer_ESP32_SC_W6100 library v1.2.1+ if necessary to use ESP32_S2/S3/C3 boards using LwIP W6100 Ethernet. To install, check arduino-library-badge

Installation

Use Arduino Library Manager

The best and easiest way is to use Arduino Library Manager. Search for HTTPS_Server_Generic, then select / install the latest version. You can also use this link arduino-library-badge for more detailed instructions.

Manual Install

  1. Navigate to HTTPS_Server_Generic page.
  2. Download the latest release HTTPS_Server_Generic-main.zip.
  3. Extract the zip file to HTTPS_Server_Generic-main directory
  4. Copy the whole HTTPS_Server_Generic-main folder to Arduino libraries' directory such as ~/Arduino/libraries/.

VS Code & PlatformIO:

  1. Install VS Code
  2. Install PlatformIO
  3. Install HTTPS_Server_Generic library by using Library Manager. Search for HTTPS_Server_Generic in Platform.io Author's Libraries
  4. Use included platformio.ini file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at Project Configuration File


Get Started

The following includes is required to setup the server.

#include <HTTPS_Server_Generic.h>

// The HTTPS Server comes in a separate namespace. For easier use, include it here.
using namespace httpsserver;

Create Server Instance

You can create your server instance like shown below:

For HTTP:

HTTPServer myServer = HTTPServer();

For HTTPS:

// Create an SSL certificate object from the files included above
SSLCert cert = SSLCert(example_crt_DER, example_crt_DER_len,
                       example_key_DER, example_key_DER_len);

// Create an SSL-enabled server that uses the certificate
HTTPSServer secureServer = HTTPSServer(&cert);

By default, the server will listen on port 443. If you want to change that (or some other options), you can have a look at the optional parameters of the HTTPServer or HTTPSServer constructors.

The only difference between the HTTP and HTTPS version is the certificate which you have to configure. Keep in mind that each opened connection of the TLS-enabled HTTPSServer requires additional 40 to 50 kB of heap memory for the TLS connection itself. This has to be considered when increasing maxConnections.


Add Resources to the Server

Every route (or path) that should be accessible on the server has to be configured as a so-called ResourceNode. Such a node links a handler function to a specific route (like /test) and HTTP method (like GET). The handler function could look like this:

void handleRoot(HTTPRequest * req, HTTPResponse * res) 
{
	// We want to deliver an HTML page, so we set the content type
	res->setHeader("Content-Type", "text/html");
	// The response implements the Print interface, so you can use it just like
	// you would write to Serial etc.
	res->println("<!DOCTYPE html>");
	res->println("<html>");
	res->println("<head><title>Hello World!</title></head>");
	res->println("<body>");
	res->println("<h1>Hello World!</h1>");
	res->print("<p>... from your ESP32!</p>");
	res->println("</body>");
	res->println("</html>");
}

As you can see, the function gets references to the HTTPRequest and HTTPResponse. You can use the request to read headers, parameters, authentication information etc. The response can be used to send data to the client, set headers or HTTP status codes.

Now we need to tell the server which URL should be served by this function. This can be done by creating a ResourceNode (usually in your setup() function).

ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot);

The first parameter defines the route. It should always start with a slash, and using just a slash like in this example means that the function will be called for requests to the server's root (like https://10.0.x.x/).

The second parameter is the HTTP method, "GET" in this case.

Finally, you pass a reference to the request handler function to link it to the route and method.

Now you just need to register the created ResourceNode at your server:

myServer.registerNode(nodeRoot);

That's everything you need to do for a single web page on your server.

Note that you can define a single ResourceNode via HTTPServer::setDefaultNode(), which will be called if no other node on the server matches. Method and route are ignored in this case. Most examples use this to define a 404-handler, which might be a good idea for most scenarios. In case no default node is specified, the server will return with a small error page if no matching route is found.


Start the Server

A call to HTTPServer::start() will start the server so that it is listening on the previously specified port:

myServer.start();

This code usually goes into your setup() function. You can use HTTPServer::isRunning() to check whether the server started successfully.

By default, you need to pass control to the server explicitly. This is done by calling the HTTPServer::loop() function, which you usually will put into your Arduino sketch's loop() function. Once called, the server will first check for incoming connection (up to the maximum connection count that has been defined in the constructor), and then handle every open connection if it has new data on the socket. So your request handler functions will be called during the call to loop(). Note that if one of your handler functions is blocking, it will block all other connections as well.


Running the Server asynchronously

If you want to have the server running in the background (and not calling loop() by yourself every few milliseconds), you can make use of the ESP32's task feature and put the whole server in a separate task.

See the Async-Server example to see how this can be done.



Advanced Configuration

This section covers some advanced configuration options that allow you, for example, to customize the build process, but which might require more advanced programming skills and a more sophisticated IDE that just the default Arduino IDE.


Saving Space by Reducing Functionality

To save program space on the microcontroller, there are some parts of the library that can be disabled during compilation and will then not be a part of your program.

The following flags are currently available:

Flag Effect
HTTPS_DISABLE_SELFSIGNING Removes the code for generating a self-signed certificate at runtime. You will need to provide certificate and private key data from another data source to use the HTTPSServer.

Setting these flags requires a build environment that gives you some control of the compiler, as libraries are usually compiled separately, so just doing a #define HTTPS_SOMETHING in your sketch will not work.


Example: Configuration with PlatformIO

To set these flags in PlatformIO, you can modify your platformio.ini. To disable for example the self-signed-certificates part of the library, the file could look like this:

[env:wroom]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps = khoih-prog/HTTPS_Server_Generic@~1.5.0
build_flags =
  -DHTTPS_DISABLE_SELFSIGNING

Note the -D in front of the actual flag name, that passes this flag as a definition to the preprocessor. Multiple flags can be added one per line.


Configure Logging

The server provides some internal logging, which is activated on level INFO by default. This will look like this on your serial console:

[HTTPS:I] New connection. SocketFID=49
[HTTPS:I] Request: GET / (FID=49)
[HTTPS:I] Connection closed. Socket FID=49

Logging output can also be controlled by using compiler flags. This requires an advanced development environment like explained in Saving Space by Reducing Functionality.

There are two parameters that can be configured:

  • HTTPS_LOGLEVEL defines the log level to use
  • HTTPS_LOGTIMESTAMP adds a timestamp (based on uptime) to each log entry
Value of HTTPS_LOGLEVEL Error Warning Info Debug
0
1
2
3
4

Example: Configuration with PlatformIO

To set these flags in PlatformIO, you can modify your platformio.ini. The following entries set the minimum log level to warning and enable timestamps

[env:wroom]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps = khoih-prog/HTTPS_Server_Generic@~1.5.0
build_flags =
  -DHTTPS_LOGLEVEL=2
  -DHTTPS_LOGTIMESTAMP


How to connect W5500, W6100 or ENC28J60 to ESP32_S2/S3/C3

W6100

FULL_DUPLEX, 100Mbps


W5500

FULL_DUPLEX, 100Mbps


ENC28J60

FULL_DUPLEX, 10Mbps


ESP32S3_DEV

You can change the INT pin to another one. Default is GPIO4

// Must connect INT to GPIOxx or not working
#define INT_GPIO            4

W5500, W6100 or ENC28J60 <---> ESP32_S3
MOSI <---> GPIO11
MISO <---> GPIO13
SCK <---> GPIO12
CS/SS <---> GPIO10
INT <---> GPIO4
RST <---> RST
GND <---> GND
3.3V <---> 3.3V

ESP32S2_DEV

You can change the INT pin to another one. Default is GPIO4

// Must connect INT to GPIOxx or not working
#define INT_GPIO            4
W5500, W6100 or ENC28J60 <---> ESP32_S2
MOSI <---> GPIO35
MISO <---> GPIO37
SCK <---> GPIO36
CS/SS <---> GPIO34
INT <---> GPIO4
RST <---> RST
GND <---> GND
3.3V <---> 3.3V

ESP32C3_DEV

You can change the INT pin to another one. Default is GPIO4

// Must connect INT to GPIOxx or not working
#define INT_GPIO            10
W5500, W6100 or ENC28J60 <---> ESP32_C3
MOSI <---> GPIO6
MISO <---> GPIO5
SCK <---> GPIO4
CS/SS <---> GPIO7
INT <---> GPIO10
RST <---> RST
GND <---> GND
3.3V <---> 3.3V


HOWTO Example Usage

You will find several examples showing how you can use the library:

  • Static-Page: Short example showing how to serve some static resources with the server. You should start with this sketch and get familiar with it before having a look at the more complex examples.
  • Parameters: Shows how you can access request parameters (the part after the question mark in the URL) or parameters in dynamic URLs (like /led/1, /led/2, ...)
  • Put-Post-Echo: Implements a simple echo service for PUT and POST requests that returns the request body as response body. Also shows how to differentiate between multiple HTTP methods for the same URL.
  • HTTPS-and-HTTP: Shows how to serve resources via HTTP and HTTPS in parallel and how to check if the user is using a secure connection during request handling
  • Middleware: Shows how to use the middleware API for logging. Middleware functions are defined very similar to webservers like Express.
  • Authentication: Implements a chain of two middleware functions to handle authentication and authorization using HTTP Basic Auth.
  • Async-Server: Like the Static-Page example, but the server runs in a separate task on the ESP32, so you do not need to call the loop() function in your main sketch.
  • Websocket-Chat: Provides a browser-based chat built on top of websockets. Note: Websockets are still under development!
  • Parameter-Validation: Shows how you can integrate validator functions to do formal checks on parameters in your URL.
  • Self-Signed-Certificate: Shows how to generate a self-signed certificate on the fly on the ESP when the sketch starts. You do not need to run create_cert.sh to use this example.
  • REST-API: Uses ArduinoJSON and SPIFFS file upload to serve a small web interface that provides a REST API.


Examples

For ESP32_WiFi

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For WT32_ETH01

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For ESP32_W5500

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For ESP32_W6100

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For ESP32_ENC

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For ESP32_SC_W5500

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For ESP32_SC_W6100

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat

For ESP32_SC_ENC

  1. Async-Server
  2. Authentication
  3. HTML-Forms
  4. HTTPS-and-HTTP
  5. Middleware
  6. Parameters
  7. Parameter-Validation
  8. Put-Post-Echo
  9. REST-API
  10. Self-Signed-Certificate
  11. Static-Page
  12. Websocket-Chat


Example Async-Server

/** Check if we have multiple cores */
#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif
// Include certificate data (see note above)
#include "cert.h"
#include "private_key.h"
//////////////////////////////////////////////////
// For ESP32_W5500
#define DEBUG_ETHERNET_WEBSERVER_PORT Serial
// Debug Level from 0 to 4
#define _ETHERNET_WEBSERVER_LOGLEVEL_ 3
//////////////////////////////////////////////////////////
// Optional values to override default settings
// Don't change unless you know what you're doing
//#define ETH_SPI_HOST SPI3_HOST
//#define SPI_CLOCK_MHZ 25
// Must connect INT to GPIOxx or not working
//#define INT_GPIO 4
//#define MISO_GPIO 19
//#define MOSI_GPIO 23
//#define SCK_GPIO 18
//#define CS_GPIO 5
//////////////////////////////////////////////////////////
#include <WebServer_ESP32_W5500.h>
//////////////////////////////////////////////////
// Enter a MAC address and IP address for your controller below.
#define NUMBER_OF_MAC 20
byte mac[][NUMBER_OF_MAC] =
{
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x02 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x03 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x04 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x05 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x06 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x07 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x08 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x09 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0B },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0C },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0D },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0E },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0F },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x10 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x11 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x12 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x13 },
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x14 },
};
// Select the IP address according to your local network
IPAddress myIP(192, 168, 2, 232);
IPAddress myGW(192, 168, 2, 1);
IPAddress mySN(255, 255, 255, 0);
// Google DNS Server IP
IPAddress myDNS(8, 8, 8, 8);
//////////////////////////////////////////////////
#include <HTTPS_Server_Generic.h>
// The HTTPS Server comes in a separate namespace. For easier use, include it here.
using namespace httpsserver;
// Create an SSL certificate object from the files included above
SSLCert cert = SSLCert(
example_crt_DER, example_crt_DER_len,
example_key_DER, example_key_DER_len
);
// Create an SSL-enabled server that uses the certificate
HTTPSServer secureServer = HTTPSServer(&cert);
void serverTask(void *params)
{
// In the separate task we first do everything that we would have done in the
// setup() function, if we would run the server synchronously.
// Note: The second task has its own stack, so you need to think about where
// you create the server's resources and how to make sure that the server
// can access everything it needs to access. Also make sure that concurrent
// access is no problem in your sketch or implement countermeasures like locks
// or mutexes.
// Create nodes
ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot);
ResourceNode * node404 = new ResourceNode("", "GET", &handle404);
// Add nodes to the server
secureServer.registerNode(nodeRoot);
secureServer.setDefaultNode(node404);
Serial.println("Starting server...");
secureServer.start();
if (secureServer.isRunning())
{
Serial.println("Server ready.");
// "loop()" function of the separate task
while (true)
{
// This call will let the server do its work
secureServer.loop();
// Other code would go here...
delay(1);
}
}
}
void handleRoot(HTTPRequest * req, HTTPResponse * res)
{
// Status code is 200 OK by default.
// We want to deliver a simple HTML page, so we send a corresponding content type:
res->setHeader("Content-Type", "text/html");
// The response implements the Print interface, so you can use it just like
// you would write to Serial etc.
res->println("<!DOCTYPE html>");
res->println("<html>");
res->println("<head><title>Hello World!</title></head>");
res->println("<body>");
res->println("<h1>Hello World!</h1>");
res->print("<p>Your server is running for ");
// A bit of dynamic data: Show the uptime
res->print((int)(millis() / 1000), DEC);
res->println(" seconds.</p>");
res->println("</body>");
res->println("</html>");
}
void handle404(HTTPRequest * req, HTTPResponse * res)
{
// Discard request body, if we received any
// We do this, as this is the default node and may also server POST/PUT requests
req->discardRequestBody();
// Set the response status
res->setStatusCode(404);
res->setStatusText("Not Found");
// Set content type of the response
res->setHeader("Content-Type", "text/html");
// Write a tiny HTTP page
res->println("<!DOCTYPE html>");
res->println("<html>");
res->println("<head><title>Not Found</title></head>");
res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>");
res->println("</html>");
}
void setup()
{
// For logging
Serial.begin(115200);
while (!Serial && millis() < 5000);
///////////////////////////////////////////////
Serial.print("\nStarting Async_Server on " + String(ARDUINO_BOARD));
Serial.println(" with " + String(SHIELD_TYPE));
Serial.println(WEBSERVER_ESP32_W5500_VERSION);
Serial.println(HTTPS_SERVER_GENERIC_VERSION);
///////////////////////////////////
// To be called before ETH.begin()
ESP32_W5500_onEvent();
// start the ethernet connection and the server:
// Use DHCP dynamic IP and random mac
uint16_t index = millis() % NUMBER_OF_MAC;
//bool begin(int MISO_GPIO, int MOSI_GPIO, int SCLK_GPIO, int CS_GPIO, int INT_GPIO, int SPI_CLOCK_MHZ,
// int SPI_HOST, uint8_t *W5500_Mac = W5500_Default_Mac);
//ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST );
ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST, mac[index] );
// Static IP, leave without this line to get IP via DHCP
//bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = 0, IPAddress dns2 = 0);
//ETH.config(myIP, myGW, mySN, myDNS);
ESP32_W5500_waitForConnect();
///////////////////////////////////
Serial.print(F("HTTPS EthernetWebServer is @ IP : "));
Serial.println(ETH.localIP());
Serial.print(F("To access, use https://"));
Serial.println(ETH.localIP());
///////////////////////////////////////////////
// Setup the server as a separate task.
Serial.println("Creating server task... ");
// We pass:
// serverTask - the function that should be run as separate task
// "https443" - a name for the task (mainly used for logging)
// 6144 - stack size in byte. If you want up to four clients, you should
// not go below 6kB. If your stack is too small, you will encounter
// Panic and stack canary exceptions, usually during the call to
// SSL_accept.
xTaskCreatePinnedToCore(serverTask, "https443", 6144, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
}
void loop()
{
Serial.println("loop()");
delay(5000);
}



Debug Terminal Output Samples

1. Async_Server on ESP32_DEV with ESP32_ENC28J60

Following are debug terminal output when running example Async-Server on ESP32_DEV with LwIP ENC28J60, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32_DEV with ESP32_ENC28J60
WebServer_ESP32_ENC v1.5.1 for core v2.0.0+
HTTPS_Server_Generic v1.5.0

ETH Started
ETH Connected
ETH MAC: DE:AD:BE:EF:BE:14, IPv4: 192.168.2.232
FULL_DUPLEX, 10Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.232
To access, use https://192.168.2.232
Creating server task... 
loop()
Starting server...
Server ready.
[HTTPS:I] New connection. Socket FID=49
loop()
[HTTPS:I] New connection. Socket FID=50
[HTTPS:I] Request: GET / (FID=49)
loop()
loop()
[HTTPS:I] Request: GET / (FID=49)
loop()
...

2. Async_Server on ESP32_DEV with ESP32_W5500

Following are debug terminal output when running example Async-Server on ESP32_DEV with LwIP W5500, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32_DEV with ESP32_W5500
WebServer_ESP32_W5500 v1.5.2 for core v2.0.0+
HTTPS_Server_Generic v1.5.0

ETH Started
ETH Connected
ETH MAC: DE:AD:BE:EF:BE:08, IPv4: 192.168.2.88
FULL_DUPLEX, 100Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.88
To access, use https://192.168.2.88
Creating server task... 
loop()
Starting server...
Server ready.
[HTTPS:I] New connection. Socket FID=49
[HTTPS:I] Request: GET / (FID=49)
loop()
[HTTPS:I] Request: GET / (FID=49)
loop()
[HTTPS:I] Request: GET / (FID=49)
loop()
.

3. Async_Server on ESP32S3_DEV with ESP32_S3_ENC28J60

Following are debug terminal output when running example Async-Server on ESP32S3_DEV with LwIP ENC28J60, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32S3_DEV with ESP32_S3_ENC28J60
WebServer_ESP32_SC_ENC v1.2.0 for core v2.0.0+
HTTPS_Server_Generic v1.5.0

ETH Started
ETH Connected
ETH MAC: DE:AD:BE:EF:FE:03, IPv4: 192.168.2.232
FULL_DUPLEX, 10Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.232
To access, use https://192.168.2.232
Creating server task... 
loop()
Starting server...
Server ready.
loop()
loop()
[HTTPS:I] New connection. Socket FID=49
loop()
[HTTPS:I] New connection. Socket FID=50
[HTTPS:I] Request: GET / (FID=49)
loop()
loop()
loop()
loop()
[HTTPS:I] Connection timeout. FID=50
[HTTPS:I] Connection closed. Socket FID=50
[HTTPS:I] Connection timeout. FID=49
[HTTPS:I] Connection closed. Socket FID=49
loop()
...

4. Async_Server on ESP32S3_DEV with ESP32_S3_W5500

Following are debug terminal output when running example Async-Server on ESP32S3_DEV with LwIP W5500, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32S3_DEV with ESP32_S3_W5500
WebServer_ESP32_SC_W5500 v1.2.1 for core v2.0.0+
HTTPS_Server_Generic v1.5.0

ETH Started
ETH Connected
ETH MAC: DE:AD:BE:EF:BE:14, IPv4: 192.168.2.89
FULL_DUPLEX, 100Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.89
To access, use https://192.168.2.89
Creating server task... 
loop()
Starting server...
Server ready.
loop()
loop()
loop()
loop()
loop()
loop()
[HTTPS:I] New connection. Socket FID=49
[HTTPS:I] Request: GET / (FID=49)
[HTTPS:I] Request: GET /favicon.ico (FID=49)
loop()
loop()
loop()
loop()
[HTTPS:I] Connection timeout. FID=49
[HTTPS:I] Connection closed. Socket FID=49
loop()
.

5. Async_Server on ESP32C3_DEV with ESP32_C3_W5500

Following are debug terminal output when running example Async-Server on ESP32C3_DEV with LwIP W5500, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32C3_DEV with ESP32_C3_W5500
WebServer_ESP32_SC_W5500 v1.2.1 for core v2.0.0+
HTTPS_Server_Generic v1.5.0
Using built-in mac_eth = 7C:DF:A1:BC:BC:53

ETH Started
ETH Connected
ETH MAC: 7C:DF:A1:BC:BC:53, IPv4: 192.168.2.135
FULL_DUPLEX, 100Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.135
To access, use https://192.168.2.135
Creating server task... 
Starting server...
Server ready.
loop()
...
loop()
[HTTPS:I] New connection. Socket FID=49
[HTTPS:E] SSL_accept failed. Aborting handshake. FID=49
[HTTPS:I] Connection closed. Socket FID=49
loop()
[HTTPS:I] New connection. Socket FID=49
[HTTPS:E] SSL_accept failed. Aborting handshake. FID=49
[HTTPS:I] Connection closed. Socket FID=49
[HTTPS:I] New connection. Socket FID=49
[HTTPS:I] Request: GET / (FID=49)
[HTTPS:I] Request: GET /favicon.ico (FID=49)
loop()
...

6. Async_Server on ESP32_DEV with ESP32_W6100

Following are debug terminal output when running example Async-Server on ESP32_DEV with LwIP W6100, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32_DEV with ESP32_W6100
WebServer_ESP32_W6100 v1.5.2 for core v2.0.0+
HTTPS_Server_Generic v1.5.0

ETH Started
ETH Connected
ETH MAC: 0C:B8:15:D8:01:D7, IPv4: 192.168.2.158
FULL_DUPLEX, 100Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.158
To access, use https://192.168.2.158
Creating server task... 
loop()
Starting server...
Server ready.
loop()
loop()
loop()
loop()
loop()
loop()
loop()
[HTTPS:I] New connection. Socket FID=49
[HTTPS:I] Request: GET / (FID=49)
[HTTPS:I] Request: GET /favicon.ico (FID=49)
loop()
loop()
loop()
loop()
[HTTPS:I] Connection timeout. FID=49
[HTTPS:I] Connection closed. Socket FID=49
loop()
loop()
...

7. Async_Server on ESP32S3_DEV with ESP32_S3_W6100

Following are debug terminal output when running example Async-Server on ESP32S3_DEV with LwIP W6100, using ESP32 core v2.0.0+, to demonstrate the operation Async HTTPS WebServer serving multiple clients simultaneously

Starting Async_Server on ESP32S3_DEV with ESP32_S3_W6100
WebServer_ESP32_SC_W6100 v1.2.1 for core v2.0.0+
HTTPS_Server_Generic v1.5.0

ETH Started
ETH Connected
ETH MAC: FE:ED:DE:AD:BE:EF, IPv4: 192.168.2.92
FULL_DUPLEX, 100Mbps
HTTPS EthernetWebServer is @ IP : 192.168.2.92
To access, use https://192.168.2.92

Creating server task... 
loop()
Starting server...
Server ready.
loop()
loop()
[HTTPS:I] New connection. Socket FID=49
loop()
[HTTPS:I] New connection. Socket FID=50
[HTTPS:I] Request: GET / (FID=49)
loop()
loop()
loop()
loop()
[HTTPS:I] Connection timeout. FID=50
[HTTPS:I] Connection closed. Socket FID=50
[HTTPS:I] Connection timeout. FID=49
[HTTPS:I] Connection closed. Socket FID=49
loop()
loop()
loop()
...


Troubleshooting

If you get compilation errors, more often than not, you may need to install a newer version of Arduino IDE, the Arduino core or depending libraries.

Sometimes, the library will only work if you update the related core to the latest version because I'm always using the latest cores /libraries.


Issues

Submit issues to: HTTPS_Server_Generic issues



TO DO

  1. Fix bug. Add enhancement
  2. For ESP32, using ESP_TLS for future ESP-IDF v5.0 instead of to-be-deprecated OpenSSL
  3. Using ArduinoJson v6 instead of v5.13.5-
  4. Add support to more powerful-enough boards using LwIP WiFi/Ethernet, such as :
  • ESP8266 WiFi / Ethernet
  • Portenta_H7 WiFi / Ethernet
  • RP2040W WiFi
  • Teensy 4.1 QNEthernet
  • etc.

DONE

  1. Initial port to ESP32 boards using LwIP Ethernet, such as WT32_ETH01, ESP32_W5500, ESP32_ENC
  2. Add Table-of-Contents and Version String
  3. Use allman astyle and add utils
  4. Add support to ESP32S3 using LwIP W5500 or ENC28J60
  5. Add support to ESP32S2/C3 using LwIP W5500 or ENC28J60
  6. Add support to ESP32 and ESP32S2/S3/C3 boards using LwIP W6100 Ethernet


Contributions and Thanks

  1. Based on and modified from Frank Hessel's esp32_https_server. Many thanks to Frank Hessel for the great esp32_https_server library
fhessel
⭐️⭐️ Frank Hessel


Contributing

If you want to contribute to this project:

  • Report bugs and errors
  • Ask for enhancements
  • Create issues and pull requests
  • Tell other people about this library

License

  • The library is licensed under MIT

Copyright

  • Copyright (c) 2017- Frank Hessel

  • Copyright (c) 2022- Khoi Hoang