| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,7 +20,7 @@ The library is self-contained and just needs the Arduino and ESP32 system librar | |||
| 20 | 20 | ||
| 21 | 21 | Clone or download the content of this git repository into your Arduino/libraries folder and restart you IDE. | |
| 22 | 22 | ||
| 23 | - To run the examples, you need to execute the script extras/create_cert.sh first. This script will create a simple CA to sign certificates that are used with the examples. Some notes on the usage can be found in the extras/README.md file. | ||
| 23 | + To run the examples (except for the _Self-Signed-Certificates_ example), you need to execute the script extras/create_cert.sh first. This script will create a simple CA to sign certificates that are used with the examples. Some notes on the usage can be found in the extras/README.md file. | ||
| 24 | 24 | ||
| 25 | 25 | You then should be able to add the library to your project if you selected the ESP32 as architecture. | |
| 26 | 26 | ||
@@ -37,6 +37,7 @@ You will find several examples showing how you can use the library: | |||
| 37 | 37 | - [Async-Server](examples/Async-Server/Async-Server.ino): 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. | |
| 38 | 38 | - [Websocket-Chat](examples/Websocket-Chat/Websocket-Chat.ino): Provides a browser-based chat built on top of websockets. **Note:** Websockets are still under development! | |
| 39 | 39 | - [Parameter-Validation](examples/Parameter-Validation/Parameter-Validation.ino): Shows how you can integrate validator functions to do formal checks on parameters in your URL. | |
| 40 | + - [Self-Signed-Certificate](examples/Self-Signed/Self-Signed.ino): 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. | ||
| 40 | 41 | ||
| 41 | 42 | If you encounter error messages that cert.h or private\_key.h are missing when running an example, make sure to run create\_cert.sh first (see Setup Instructions). | |
| 42 | 43 | ||
@@ -144,4 +145,35 @@ By default, you need to pass control to the server explicitly. This is done by c | |||
| 144 | 145 | ||
| 145 | 146 | 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. | |
| 146 | 147 | ||
| 147 | - See the Async-Server example to see how this can be done. | ||
| 148 | + See the Async-Server example to see how this can be done. | ||
| 149 | + | ||
| 150 | + ## Advanced Configuration | ||
| 151 | + | ||
| 152 | + This section covers some advanced configuration options that allow you e.g. to customize the build process, but which might require more advanced programming skills and a more sophisticated IDE that just the default Arduino IDE. | ||
| 153 | + | ||
| 154 | + ### Saving Space by Reducing Functionality | ||
| 155 | + | ||
| 156 | + 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. | ||
| 157 | + | ||
| 158 | + The following flags are currently available: | ||
| 159 | + | ||
| 160 | + | Flag | Effect | ||
| 161 | + | ------------------------- | --------------------------- | ||
| 162 | + | 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`. | ||
| 163 | + | ||
| 164 | + 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. | ||
| 165 | + | ||
| 166 | + **Example: Configuration with Platform IO** | ||
| 167 | + | ||
| 168 | + To set these flags in Platform IO, you can modify your `platformio.ini`. To disable for example the self-signed-certificates part of the library, the file could look like this: | ||
| 169 | + | ||
| 170 | + ```ini | ||
| 171 | + [env:esp32dev] | ||
| 172 | + platform = espressif32 | ||
| 173 | + board = esp32dev | ||
| 174 | + framework = arduino | ||
| 175 | + build_flags = | ||
| 176 | + -DHTTPS_DISABLE_SELFSIGNING | ||
| 177 | + ``` | ||
| 178 | + | ||
| 179 | + 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. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,164 @@ | |||
| 1 | + /** | ||
| 2 | + * Example for the ESP32 HTTP(S) Webserver | ||
| 3 | + * | ||
| 4 | + * IMPORTANT NOTE: | ||
| 5 | + * To run this script, you need to | ||
| 6 | + * 1) Enter your WiFi SSID and PSK below this comment | ||
| 7 | + * | ||
| 8 | + * This script will install an HTTPS Server on your ESP32 with the following | ||
| 9 | + * functionalities: | ||
| 10 | + * - Show simple page on web server root | ||
| 11 | + * - 404 for everything else | ||
| 12 | + * | ||
| 13 | + * In contrast to the other examples, the certificate and the private key will be | ||
| 14 | + * generated on the ESP32, so you do not need to provide them here. | ||
| 15 | + * (this means no need to run create_cert.sh) | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | + // TODO: Configure your WiFi here | ||
| 19 | + #define WIFI_SSID "<your ssid goes here>" | ||
| 20 | + #define WIFI_PSK "<your pre-shared key goes here>" | ||
| 21 | + | ||
| 22 | + // We will use wifi | ||
| 23 | + #include <WiFi.h> | ||
| 24 | + | ||
| 25 | + // Includes for the server | ||
| 26 | + #include <HTTPSServer.hpp> | ||
| 27 | + #include <SSLCert.hpp> | ||
| 28 | + #include <HTTPRequest.hpp> | ||
| 29 | + #include <HTTPResponse.hpp> | ||
| 30 | + | ||
| 31 | + // The HTTPS Server comes in a separate namespace. For easier use, include it here. | ||
| 32 | + using namespace httpsserver; | ||
| 33 | + | ||
| 34 | + SSLCert * cert; | ||
| 35 | + HTTPSServer * secureServer; | ||
| 36 | + | ||
| 37 | + // Declare some handler functions for the various URLs on the server | ||
| 38 | + void handleRoot(HTTPRequest * req, HTTPResponse * res); | ||
| 39 | + void handle404(HTTPRequest * req, HTTPResponse * res); | ||
| 40 | + | ||
| 41 | + void setup() { | ||
| 42 | + // For logging | ||
| 43 | + Serial.begin(115200); | ||
| 44 | + delay(3000); // wait for the monitor to reconnect after uploading. | ||
| 45 | + | ||
| 46 | + Serial.println("Creating a new self-signed certificate."); | ||
| 47 | + Serial.println("This may take up to a minute, so be patient ;-)"); | ||
| 48 | + | ||
| 49 | + // First, we create an empty certificate: | ||
| 50 | + cert = new SSLCert(); | ||
| 51 | + | ||
| 52 | + // Now, we use the function createSelfSignedCert to create private key and certificate. | ||
| 53 | + // The function takes the following paramters: | ||
| 54 | + // - Key size: 1024 or 2048 bit should be fine here, 4096 on the ESP might be "paranoid mode" | ||
| 55 | + // (in generel: shorter key = faster but less secure) | ||
| 56 | + // - Distinguished name: The name of the host as used in certificates. | ||
| 57 | + // If you want to run your own DNS, the part after CN (Common Name) should match the DNS | ||
| 58 | + // entry pointing to your ESP32. You can try to insert an IP there, but that's not really good style. | ||
| 59 | + int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=myesp32.local,O=FancyCompany,C=DE"); | ||
| 60 | + | ||
| 61 | + // Now check if creating that worked | ||
| 62 | + if (createCertResult != 0) { | ||
| 63 | + Serial.printf("Cerating certificate failed. Error Code = 0x%02X, check SSLCert.hpp for details", createCertResult); | ||
| 64 | + while(true) delay(500); | ||
| 65 | + } | ||
| 66 | + Serial.println("Creating the certificate was successful"); | ||
| 67 | + | ||
| 68 | + // If you're working on a serious project, this would be a good place to initialize some form of non-volatile storage | ||
| 69 | + // and to put the certificate and the key there. This has the advantage that the certificate stays the same after a reboot | ||
| 70 | + // so your client still trusts your server, additionally you increase the speed-up of your application. | ||
| 71 | + // Some browsers like Firefox might even reject the second run for the same issuer name (the distinguished name defined above). | ||
| 72 | + // | ||
| 73 | + // Storing: | ||
| 74 | + // For the key: | ||
| 75 | + // cert->getPKLength() will return the length of the private key in byte | ||
| 76 | + // cert->getPKData() will return the actual private key (in DER-format, if that matters to you) | ||
| 77 | + // For the certificate: | ||
| 78 | + // cert->getCertLength() and ->getCertData() do the same for the actual certificate data. | ||
| 79 | + // Restoring: | ||
| 80 | + // When your applications boots, check your non-volatile storage for an existing certificate, and if you find one | ||
| 81 | + // use the parameterized SSLCert constructor to re-create the certificate and pass it to the HTTPSServer. | ||
| 82 | + // | ||
| 83 | + // A short reminder on key security: If you're working on something professional, be aware that the storage of the ESP32 is | ||
| 84 | + // not encrypted in any way. This means that if you just write it to the flash storage, it is easy to extract it if someone | ||
| 85 | + // gets a hand on your hardware. You should decide if that's a relevant risk for you and apply countermeasures like flash | ||
| 86 | + // encryption if neccessary | ||
| 87 | + | ||
| 88 | + // We can now use the new certificate to setup our server as usual. | ||
| 89 | + secureServer = new HTTPSServer(cert); | ||
| 90 | + | ||
| 91 | + // Connect to WiFi | ||
| 92 | + Serial.println("Setting up WiFi"); | ||
| 93 | + WiFi.begin(WIFI_SSID, WIFI_PSK); | ||
| 94 | + while (WiFi.status() != WL_CONNECTED) { | ||
| 95 | + Serial.print("."); | ||
| 96 | + delay(500); | ||
| 97 | + } | ||
| 98 | + Serial.print("Connected. IP="); | ||
| 99 | + Serial.println(WiFi.localIP()); | ||
| 100 | + | ||
| 101 | + // For every resource available on the server, we need to create a ResourceNode | ||
| 102 | + // The ResourceNode links URL and HTTP method to a handler function | ||
| 103 | + ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot); | ||
| 104 | + ResourceNode * node404 = new ResourceNode("", "GET", &handle404); | ||
| 105 | + | ||
| 106 | + // Add the root node to the server | ||
| 107 | + secureServer->registerNode(nodeRoot); | ||
| 108 | + // Add the 404 not found node to the server. | ||
| 109 | + secureServer->setDefaultNode(node404); | ||
| 110 | + | ||
| 111 | + Serial.println("Starting server..."); | ||
| 112 | + secureServer->start(); | ||
| 113 | + if (secureServer->isRunning()) { | ||
| 114 | + Serial.println("Server ready."); | ||
| 115 | + } | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + void loop() { | ||
| 119 | + // This call will let the server do its work | ||
| 120 | + secureServer->loop(); | ||
| 121 | + | ||
| 122 | + // Other code would go here... | ||
| 123 | + delay(1); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + void handleRoot(HTTPRequest * req, HTTPResponse * res) { | ||
| 127 | + // Status code is 200 OK by default. | ||
| 128 | + // We want to deliver a simple HTML page, so we send a corresponding content type: | ||
| 129 | + res->setHeader("Content-Type", "text/html"); | ||
| 130 | + | ||
| 131 | + // The response implements the Print interface, so you can use it just like | ||
| 132 | + // you would write to Serial etc. | ||
| 133 | + res->println("<!DOCTYPE html>"); | ||
| 134 | + res->println("<html>"); | ||
| 135 | + res->println("<head><title>Hello World!</title></head>"); | ||
| 136 | + res->println("<body>"); | ||
| 137 | + res->println("<h1>Hello World!</h1>"); | ||
| 138 | + res->print("<p>Your server is running for "); | ||
| 139 | + // A bit of dynamic data: Show the uptime | ||
| 140 | + res->print((int)(millis()/1000), DEC); | ||
| 141 | + res->println(" seconds.</p>"); | ||
| 142 | + res->println("</body>"); | ||
| 143 | + res->println("</html>"); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + void handle404(HTTPRequest * req, HTTPResponse * res) { | ||
| 147 | + // Discard request body, if we received any | ||
| 148 | + // We do this, as this is the default node and may also server POST/PUT requests | ||
| 149 | + req->discardRequestBody(); | ||
| 150 | + | ||
| 151 | + // Set the response status | ||
| 152 | + res->setStatusCode(404); | ||
| 153 | + res->setStatusText("Not Found"); | ||
| 154 | + | ||
| 155 | + // Set content type of the response | ||
| 156 | + res->setHeader("Content-Type", "text/html"); | ||
| 157 | + | ||
| 158 | + // Write a tiny HTTP page | ||
| 159 | + res->println("<!DOCTYPE html>"); | ||
| 160 | + res->println("<html>"); | ||
| 161 | + res->println("<head><title>Not Found</title></head>"); | ||
| 162 | + res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>"); | ||
| 163 | + res->println("</html>"); | ||
| 164 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments