Skip to content

Commit 714601c

Browse files
Ivan KostoskiIvan Kostoski
authored andcommitted
HTTPS-Workers demo
1 parent 5565d57 commit 714601c

17 files changed

+239
-0
lines changed
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/**
2+
* Example for the ESP32 HTTP(S) Webserver
3+
*
4+
* IMPORTANT NOTE:
5+
* To run this script, your need to
6+
* 1) Enter your WiFi SSID and PSK below this comment
7+
* 2) Make sure to have certificate data available. You will find a
8+
* shell script and instructions to do so in the library folder
9+
* under extras/
10+
*
11+
* This script will install an HTTPS Server on your ESP32 with the following
12+
* functionalities:
13+
* - Use of TLS Tickets (RFC 5077)
14+
* - Use of server workers in separate FreeRTOS tasks
15+
* - Show simple page on web server root
16+
* - Paralell serving of multiple images (cats.html)
17+
*
18+
*/
19+
20+
/**
21+
* NOTE: You need to upload the data directory to SPIFFS
22+
*
23+
* Cat images in data folder were taken from:
24+
* https://unsplash.com/search/photos/cat
25+
* License: https://unsplash.com/license
26+
*/
27+
28+
// TODO: Configure your WiFi here
29+
#define WIFI_SSID "<your ssid goes here>"
30+
#define WIFI_PSK "<your pre-shared key goes here>"
31+
32+
// Adjust these for available memory
33+
#define MAX_CONNECTIONS 2
34+
#define NUM_WORKERS 2
35+
36+
//Delay image sending, milisecods between 256 bytes blocks.
37+
//Can be used to visualize parallel connection handling
38+
#define IMAGE_SLOWDOWN 10
39+
40+
// Include certificate data (see note above)
41+
#include "cert.h"
42+
#include "private_key.h"
43+
44+
// We will use wifi
45+
#include <WiFi.h>
46+
47+
// And images stored in SPIFFS
48+
#include "FS.h"
49+
#include "SPIFFS.h"
50+
51+
// Includes for the server
52+
#include <HTTPSServer.hpp>
53+
#include <SSLCert.hpp>
54+
#include <HTTPRequest.hpp>
55+
#include <HTTPResponse.hpp>
56+
#include <cJSON.h>
57+
58+
// The HTTPS Server comes in a separate namespace. For easier use, include it here.
59+
using namespace httpsserver;
60+
61+
// Create an SSL certificate object from the files included above
62+
SSLCert cert = SSLCert(
63+
example_crt_DER, example_crt_DER_len,
64+
example_key_DER, example_key_DER_len
65+
);
66+
67+
// Create an TLS-enabled server that uses the certificate
68+
HTTPSServer secureServer = HTTPSServer(&cert, 443, MAX_CONNECTIONS);
69+
70+
// Declare some handler functions for the various URLs on the server
71+
void handleRoot(HTTPRequest * req, HTTPResponse * res);
72+
void handleCatIndex(HTTPRequest * req, HTTPResponse * res);
73+
void handleDefault(HTTPRequest * req, HTTPResponse * res);
74+
75+
void setup() {
76+
// For logging
77+
Serial.begin(115200);
78+
79+
// Check SPIFFS data
80+
if (!SPIFFS.begin(false)) {
81+
Serial.println("Please upload SPIFFS data for this sketch.");
82+
while(1);
83+
}
84+
85+
// Connect to WiFi
86+
Serial.println("Setting up WiFi");
87+
WiFi.begin(WIFI_SSID, WIFI_PSK);
88+
while (WiFi.status() != WL_CONNECTED) {
89+
Serial.print(".");
90+
delay(500);
91+
}
92+
Serial.print("Connected. IP=");
93+
Serial.println(WiFi.localIP());
94+
95+
Serial.println("Memory before server start:");
96+
Serial.print(" heap size = "); Serial.println(heap_caps_get_free_size(MALLOC_CAP_8BIT));
97+
Serial.print(" largest free block = "); Serial.println(heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
98+
99+
// Add nodes to the server
100+
secureServer.registerNode(new ResourceNode("/", "GET", &handleRoot));
101+
secureServer.registerNode(new ResourceNode("/cats.html", "GET", &handleCatIndex));
102+
secureServer.setDefaultNode(new ResourceNode("", "GET", &handleDefault));
103+
104+
Serial.println("Starting server...");
105+
106+
// We want to use RFC5077 TLS ticket for faster
107+
// TLS connenction negotiation once one connection
108+
// was established. Tickets are by default valid
109+
// for one day
110+
// Must be configure before you start the server
111+
secureServer.enableTLSTickets();
112+
113+
// Enable two FreeRTOS task that will independedntly
114+
// handle all server functions and resource callbacks
115+
// Must be configure before you start the server
116+
secureServer.enableWorkers(NUM_WORKERS);
117+
118+
// And finally start the HTTPS server
119+
secureServer.start();
120+
121+
// We are done. You are free to use the loop() function
122+
// without minding the server... that is if you still have
123+
// RAM available...
124+
125+
if (secureServer.isRunning()) {
126+
Serial.println("Server is running.");
127+
}
128+
129+
Serial.println("Memory after server start:");
130+
Serial.print(" heap size = "); Serial.println(heap_caps_get_free_size(MALLOC_CAP_8BIT));
131+
Serial.print(" largest free block = "); Serial.println(heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
132+
}
133+
134+
void loop() {
135+
Serial.println("main loop()");
136+
delay(5000);
137+
}
138+
139+
// HTTPS Server handlers
140+
141+
void handleRoot(HTTPRequest * req, HTTPResponse * res) {
142+
// Status code is 200 OK by default.
143+
// We want to deliver a simple HTML page, so we send a corresponding content type:
144+
res->setHeader("Content-Type", "text/html");
145+
146+
// The response implements the Print interface, so you can use it just like
147+
// you would write to Serial etc.
148+
res->println("<!DOCTYPE html>");
149+
res->println("<html>");
150+
res->println("<head><title>Hello World!</title></head>");
151+
res->println("<body>");
152+
res->println("<h1>Hello World!</h1>");
153+
res->print("<p>Your server is running for ");
154+
// A bit of dynamic data: Show the uptime
155+
res->print((int)(millis()/1000), DEC);
156+
res->println(" seconds.</p>");
157+
res->print("<p>Task servicing this connection is: ");
158+
res->print((uint32_t)xTaskGetCurrentTaskHandle(), HEX);
159+
res->println("</p>");
160+
res->println("<p>Here you can find some random <a href='cats.html'>cats</a></p>");
161+
res->println("</body>");
162+
res->println("</html>");
163+
}
164+
165+
/**
166+
* Generate page with links to images in SPIFFS:/cats directory
167+
*/
168+
void handleCatIndex(HTTPRequest * req, HTTPResponse * res) {
169+
// Status code is 200 OK by default.
170+
// We want to deliver a simple HTML page, so we send a corresponding content type:
171+
res->setHeader("Content-Type", "text/html");
172+
173+
// The response implements the Print interface, so you can use it just like
174+
// you would write to Serial etc.
175+
res->println("<!DOCTYPE html>");
176+
res->println("<html>");
177+
res->println("<head><title>Random cats</title></head>");
178+
res->println("<body>");
179+
File dir = SPIFFS.open("/cats");
180+
if (dir.isDirectory()) {
181+
File file = dir.openNextFile();
182+
while (file) {
183+
String filename = file.name();
184+
if (filename.endsWith(".jpg")) {
185+
res->print("<img src='");
186+
res->print(file.name());
187+
res->println("' style='width:20%;height:20%'>");
188+
}
189+
file = dir.openNextFile();
190+
}
191+
}
192+
res->println("</body>");
193+
res->println("</html>");
194+
}
195+
196+
// Default handler looks for matching file in SPIFFS
197+
// and sends it, otherwise retuns 404
198+
void handleDefault(HTTPRequest * req, HTTPResponse * res) {
199+
// Discard request body, if we received any
200+
req->discardRequestBody();
201+
202+
// Find the file in SPIFFS
203+
String filename = String(req->getRequestString().c_str());
204+
if (!SPIFFS.exists(filename)) {
205+
// File doesn't exist, return 404
206+
res->setStatusCode(404);
207+
res->setStatusText("Not found");
208+
// Write a tiny HTTP page
209+
res->setHeader("Content-Type", "text/html");
210+
res->println("<!DOCTYPE html>");
211+
res->println("<html>");
212+
res->println("<head><title>Not Found</title></head>");
213+
res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>");
214+
res->println("</html>");
215+
return;
216+
}
217+
File file = SPIFFS.open(filename);
218+
219+
// Set headers, "Content-Length" is important!
220+
res->setHeader("Content-Length", httpsserver::intToString(file.size()));
221+
res->setHeader("Content-Type", "image/jpg");
222+
// Informational only, if you look at developer console in your browser
223+
char taskHandle[11];
224+
sprintf(taskHandle, "0x%08x", (uint32_t)xTaskGetCurrentTaskHandle());
225+
res->setHeader("X-Task-ID", taskHandle);
226+
227+
// Allocate buffer in the task stack as this may run in parallel
228+
uint8_t buffer[256];
229+
// Send file contents
230+
size_t length = 0;
231+
do {
232+
length = file.read(buffer, sizeof(buffer));
233+
res->write(buffer, length);
234+
#if IMAGE_SLOWDOWN > 0
235+
delay(IMAGE_SLOWDOWN);
236+
#endif
237+
} while (length > 0);
238+
file.close();
239+
}
16.5 KB
Loading
19.6 KB
Loading
Loading
Loading
18.4 KB
Loading
22.3 KB
Loading
15.6 KB
Loading
31.6 KB
Loading
27 KB
Loading

0 commit comments

Comments
 (0)