|
| 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 | + * - Do the same as the Middleware.ino example |
| 14 | + * - Show how to add and remove additional middlewares with different datatypes |
| 15 | + */ |
| 16 | + |
| 17 | +// TODO: Configure your WiFi here |
| 18 | +#define WIFI_SSID "<your ssid goes here>" |
| 19 | +#define WIFI_PSK "<your pre-shared key goes here>" |
| 20 | + |
| 21 | +// Include certificate data (see note above) |
| 22 | +#include "cert.h" |
| 23 | +#include "private_key.h" |
| 24 | + |
| 25 | +// We will use wifi |
| 26 | +#include <WiFi.h> |
| 27 | + |
| 28 | +// For the middleware |
| 29 | +#include <functional> |
| 30 | + |
| 31 | +// Includes for the server |
| 32 | +#include <HTTPSServer.hpp> |
| 33 | +#include <SSLCert.hpp> |
| 34 | +#include <HTTPRequest.hpp> |
| 35 | +#include <HTTPResponse.hpp> |
| 36 | +#include <HTTPMiddlewareFunction.hpp> |
| 37 | + |
| 38 | +// The HTTPS Server comes in a separate namespace. For easier use, include it here. |
| 39 | +using namespace httpsserver; |
| 40 | + |
| 41 | +// Create an SSL certificate object from the files included above |
| 42 | +SSLCert cert = SSLCert( |
| 43 | + example_crt_DER, example_crt_DER_len, |
| 44 | + example_key_DER, example_key_DER_len |
| 45 | +); |
| 46 | + |
| 47 | +// Create an SSL-enabled server that uses the certificate |
| 48 | +// The contstructor takes some more parameters, but we go for default values here. |
| 49 | +HTTPSServer secureServer = HTTPSServer(&cert); |
| 50 | + |
| 51 | +// Declare some handler functions for the various URLs on the server |
| 52 | +void handleRoot(HTTPRequest * req, HTTPResponse * res); |
| 53 | +void handle404(HTTPRequest * req, HTTPResponse * res); |
| 54 | + |
| 55 | +// Declare a middleware function. |
| 56 | +// Parameters: |
| 57 | +// req: Request data, can be used to access URL, HTTP Method, Headers, ... |
| 58 | +// res: Response data, can be used to access HTTP Status, Headers, ... |
| 59 | +// next: This function is used to pass control down the chain. If you have done your work |
| 60 | +// with the request object, you may decide if you want to process the request. |
| 61 | +// If you do so, you call the next() function, and the next middleware function (if |
| 62 | +// there is any) or the actual requestHandler will be called. |
| 63 | +// If you want to skip the request, you do not call next, and set for example status |
| 64 | +// code 403 on the response to show that the user is not allowed to access a specific |
| 65 | +// resource. |
| 66 | +// The Authentication examples provides more details on this. |
| 67 | +void middlewareLogging(HTTPRequest * req, HTTPResponse * res, std::function<void()> next); |
| 68 | + |
| 69 | +void middlewareRawPointer(HTTPRequest * req, HTTPResponse * res, std::function<void()> next); |
| 70 | + |
| 71 | +void setup() { |
| 72 | + // For logging |
| 73 | + Serial.begin(115200); |
| 74 | + |
| 75 | + // Connect to WiFi |
| 76 | + Serial.println("Setting up WiFi"); |
| 77 | + WiFi.begin(WIFI_SSID, WIFI_PSK); |
| 78 | + while (WiFi.status() != WL_CONNECTED) { |
| 79 | + Serial.print("."); |
| 80 | + delay(500); |
| 81 | + } |
| 82 | + Serial.print("Connected. IP="); |
| 83 | + Serial.println(WiFi.localIP()); |
| 84 | + |
| 85 | + // For every resource available on the server, we need to create a ResourceNode |
| 86 | + // The ResourceNode links URL and HTTP method to a handler function |
| 87 | + ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot); |
| 88 | + ResourceNode * node404 = new ResourceNode("", "GET", &handle404); |
| 89 | + |
| 90 | + // Add the root node to the server |
| 91 | + secureServer.registerNode(nodeRoot); |
| 92 | + |
| 93 | + // Add the 404 not found node to the server. |
| 94 | + // The path is ignored for the default node. |
| 95 | + secureServer.setDefaultNode(node404); |
| 96 | + |
| 97 | + // Add the middleware. The function will be called globally for every request |
| 98 | + // Note: The functions are called in the order they are added to the server. |
| 99 | + // Also, if you want a middleware to handle only specific requests, you can check |
| 100 | + // the URL within the middleware function. |
| 101 | + secureServer.addMiddleware(middlewareLogging); |
| 102 | + secureServer.addMiddleware(middlewareRawPointer); |
| 103 | + // add a std::function middleware function |
| 104 | + const HTTPSMiddlewareFunction std_function{middlewareLogging}; |
| 105 | + secureServer.addMiddleware(std_function); |
| 106 | + const auto outside_variable = 10; |
| 107 | + // Add a lambda middleware function |
| 108 | + const auto lamda = [outside_variable](HTTPRequest * req, HTTPResponse * res, std::function<void()> next) { |
| 109 | + Serial.print("Middleware Lambda with outside variable "); |
| 110 | + Serial.println(outside_variable); |
| 111 | + }; |
| 112 | + secureServer.addMiddleware(lamda); |
| 113 | + |
| 114 | + Serial.println("Removing middlewares..."); |
| 115 | + // Remove the raw function pointer middleware |
| 116 | + secureServer.removeMiddleware(middlewareRawPointer); |
| 117 | + // Remove the std::function middleware |
| 118 | + secureServer.removeMiddleware(std_function); |
| 119 | + // Remove the lambda middleware |
| 120 | + secureServer.removeMiddleware(lamda); |
| 121 | + |
| 122 | + Serial.println("Starting server..."); |
| 123 | + secureServer.start(); |
| 124 | + if (secureServer.isRunning()) { |
| 125 | + Serial.println("Server ready."); |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +void loop() { |
| 130 | + // This call will let the server do its work |
| 131 | + secureServer.loop(); |
| 132 | + |
| 133 | + // Other code would go here... |
| 134 | + delay(1); |
| 135 | +} |
| 136 | + |
| 137 | +// We want to log the following information for every request: |
| 138 | +// - Response Status |
| 139 | +// - Request Method |
| 140 | +// - Request String (URL + Parameters) |
| 141 | +void middlewareLogging(HTTPRequest * req, HTTPResponse * res, std::function<void()> next) { |
| 142 | + // We want to print the response status, so we need to call next() first. |
| 143 | + next(); |
| 144 | + // After the call, the status is (hopefully) set by the handler function, so we can |
| 145 | + // access it for logging. |
| 146 | + Serial.printf("middlewareLogging(): %3d\t%s\t\t%s\n", |
| 147 | + // Status code (like: 200) |
| 148 | + res->getStatusCode(), |
| 149 | + // Method used for the request (like: GET) |
| 150 | + req->getMethod().c_str(), |
| 151 | + // Request string (like /index.html) |
| 152 | + req->getRequestString().c_str()); |
| 153 | +} |
| 154 | + |
| 155 | +void middlewareRawPointer(HTTPRequest * req, HTTPResponse * res, std::function<void()> next) { |
| 156 | + Serial.print("Middleware Raw Pointer"); |
| 157 | + next(); |
| 158 | +} |
| 159 | + |
| 160 | +// For details on the implementation of the hanlder functions, refer to the Static-Page example. |
| 161 | +void handleRoot(HTTPRequest * req, HTTPResponse * res) { |
| 162 | + res->setHeader("Content-Type", "text/html"); |
| 163 | + res->println("<!DOCTYPE html>"); |
| 164 | + res->println("<html>"); |
| 165 | + res->println("<head><title>Hello World!</title></head>"); |
| 166 | + res->println("<body>"); |
| 167 | + res->println("<h1>Hello World!</h1>"); |
| 168 | + res->print("<p>Your server is running for "); |
| 169 | + res->print((int)(millis()/1000), DEC); |
| 170 | + res->println(" seconds.</p>"); |
| 171 | + res->println("</body>"); |
| 172 | + res->println("</html>"); |
| 173 | +} |
| 174 | + |
| 175 | +void handle404(HTTPRequest * req, HTTPResponse * res) { |
| 176 | + req->discardRequestBody(); |
| 177 | + res->setStatusCode(404); |
| 178 | + res->setStatusText("Not Found"); |
| 179 | + res->setHeader("Content-Type", "text/html"); |
| 180 | + res->println("<!DOCTYPE html>"); |
| 181 | + res->println("<html>"); |
| 182 | + res->println("<head><title>Not Found</title></head>"); |
| 183 | + res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>"); |
| 184 | + res->println("</html>"); |
| 185 | +} |
0 commit comments