Skip to content

Commit 714601c

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

17 files changed

+239
-0
lines changed
+239
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
13.5 KB
Loading
16 KB
Loading
22.8 KB
Loading
23.4 KB
Loading
19.5 KB
Loading
15.4 KB
Loading
29.8 KB
Loading

0 commit comments

Comments
 (0)