/
SoRusV
/
esp32_https_server
Обзор
Документация
Войти
/
SoRusV
/
esp32_https_server
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
examples/Parameters/Parameters.ino
354 строки
14 KB
Frank Hessel
Modify interface to query parameters. Close #62. Close #63
05 дек 2019, 04:11
Не верифицирован
05 дек 2019, 04:11
2f50357
Код
Авторство
О чём код?
/** * Example for the ESP32 HTTP(S) Webserver * * IMPORTANT NOTE: * To run this script, your need to * 1) Enter your WiFi SSID and PSK below this comment * 2) Make sure to have certificate data available. You will find a * shell script and instructions to do so in the library folder * under extras/ * * This script will install an HTTPS Server on your ESP32 with the following * functionalities: * - Show page on web server root that will display some SVG smileys. * Using a simple HTML form and GET parameters, you can change the colors * of those images. * - Provide the svg image with an optional GET parameter that allows to * modify the background color, URL: /images/awesome.svg * - Provide an example that shows how wildcard URL parameters get parsed * URL: /urlparam/some/thing * - 404 for everything else */ // TODO: Configure your WiFi here #define WIFI_SSID "<your ssid goes here>" #define WIFI_PSK "<your pre-shared key goes here>" // Include certificate data (see note above) #include "cert.h" #include "private_key.h" // We will use wifi #include <WiFi.h> // Includes for the server #include <HTTPSServer.hpp> #include <SSLCert.hpp> #include <HTTPRequest.hpp> #include <HTTPResponse.hpp> // 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 // The contstructor takes some more parameters, but we go for default values here. HTTPSServer secureServer = HTTPSServer(&cert); // We declare some handler functions (definition at the end of the file) void handleRoot(HTTPRequest * req, HTTPResponse * res); void handleSVG(HTTPRequest * req, HTTPResponse * res); void handleQueryDemo(HTTPRequest * req, HTTPResponse * res); void handlePathParam(HTTPRequest * req, HTTPResponse * res); void handle404(HTTPRequest * req, HTTPResponse * res); void setup() { // For logging Serial.begin(115200); // Connect to WiFi Serial.println("Setting up WiFi"); WiFi.begin(WIFI_SSID, WIFI_PSK); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.print("Connected. IP="); Serial.println(WiFi.localIP()); // For every resource available on the server, we need to create a ResourceNode // The ResourceNode links URL and HTTP method to a handler function ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot); ResourceNode * nodeSVG = new ResourceNode("/images/awesome.svg", "GET", &handleSVG); ResourceNode * nodeQueryDemo = new ResourceNode("/queryparams", "GET", &handleQueryDemo); ResourceNode * node404 = new ResourceNode("", "GET", &handle404); // Path parameters // If you want (for example) to return a specific instance of an object type by its ID // you can use URLs like /led/1, led/2, ... - And you do not need to register one Resource // Node per ID, but you can use wildcards in the route definition. The following route // has two wildcards, and will match for example to /urlparam/foo/bar, where "foo" and "bar" // are accessible parameters in the handler function. // Note: The wildcards can only be used between slashes at the moment (so /urlparam* would // not work). ResourceNode * nodeURLParam = new ResourceNode("/urlparam/*/*", "GET", &handlePathParam); // Add the root node to the server secureServer.registerNode(nodeRoot); // Add the SVG image secureServer.registerNode(nodeSVG); // Query parameter demo secureServer.registerNode(nodeQueryDemo); // Add the path parameter // Note: The order of nodes may become important here. If you have one node for "/led" (e.g. list of LEDs) // and one node for /led/* (LED details), you should register the non-parameterized version first. The server // follows a first-match policy. If you would register the details node first, a call to /led/ will be targetted // at the details handler function with an empty parameter, which is probably not what you want. secureServer.registerNode(nodeURLParam); // Add the 404 not found node to the server. // The path is ignored for the default node. secureServer.setDefaultNode(node404); Serial.println("Starting server..."); secureServer.start(); if (secureServer.isRunning()) { Serial.println("Server ready."); } } void loop() { // This call will let the server do its work secureServer.loop(); // Other code would go here... delay(1); } void handleRoot(HTTPRequest * req, HTTPResponse * res) { // We will deliver an HTML page res->setHeader("Content-Type", "text/html"); // Write the response page res->println("<!DOCTYPE html>"); res->println("<html>"); res->println("<head><title>Hello World!</title></head>"); res->println("<style>.info{font-style:italic}</style>"); res->println("<body>"); res->println("<h1>Query Parameters</h1>"); res->println("<p class=\"info\">The parameters after the question mark in your URL.</p>"); // Show a form to select a color to colorize the faces // We pass the selection as get parameter "shades" to this very same page, // so we can evaluate it below res->println("<form method=\"GET\" action=\"/\">Show me faces in shades of "); res->println("<select name=\"shades\">"); res->println("<option value=\"red\">red</option>"); res->println("<option value=\"green\">green</option>"); res->println("<option value=\"blue\">blue</option>"); res->println("<option value=\"yellow\">yellow</option>"); res->println("<option value=\"cyan\">cyan</option>"); res->println("<option value=\"magenta\">magenta</option>"); res->println("<option value=\"rainbow\">rainbow</option>"); res->println("</select>"); res->println("<button type=\"submit\">Go!</button>"); res->println("</form>"); // Get the params to check if the user did select something ResourceParameters * params = req->getParams(); std::string paramName = "shades"; // Print 6 faces for(int i = 0; i < 6; i++) { // Include the image of the handleSVG function with a specific color code res->print("<img style=\"height:100px;width:100px\" src=\"images/awesome.svg?color="); // Depending on the selection we show the images in a specific color shade // Default is dark gray. int r = 63, g = 63, b = 63; std::string paramVal; if (params->getQueryParameter(paramName, paramVal)) { if (paramVal == "red" || paramVal == "magenta" || paramVal == "yellow" || paramVal == "rainbow") { r = 128 + random(0, 128); } if (paramVal == "green" || paramVal == "cyan" || paramVal == "yellow" || paramVal == "rainbow") { g = 128 + random(0, 128); } if (paramVal == "blue" || paramVal == "magenta" || paramVal == "cyan" || paramVal == "rainbow") { b = 128 + random(0, 128); } } // Print the random color. As the HTTPResponse extends the Print interface, we can make use of that. res->print(r, HEX); res->print(g, HEX); res->print(b, HEX); res->print("\" alt=\"Awesome!\" />"); } res->println("<p>You'll find another demo <a href=\"/queryparams?a=42&b&c=13&a=hello\">here</a>.</p>"); // Link to the path parameter demo res->println("<h1>Path Parameters</h1>"); res->println("<p class=\"info\">The parameters derived from placeholders in your path, like /foo/bar.</p>"); res->println("<p>You'll find the demo <a href=\"/urlparam/foo/bar\">here</a>.</p>"); res->println("</body>"); res->println("</html>"); } // This callback responds with an SVG image to a GET request. The icon is the "awesome face". // (borrowed from https://commons.wikimedia.org/wiki/File:718smiley.svg) // // If the color query parameter is set (so the URL is like awesome.svg?color=fede58), the // background of our awesome face is changed. void handleSVG(HTTPRequest * req, HTTPResponse * res) { // Get access to the parameters ResourceParameters * params = req->getParams(); // Set SVG content type res->setHeader("Content-Type", "image/svg+xml"); // Set a default color std::string fillColor = "fede58"; // Get request parameter (like awesome.svg?color=ff0000) and validate it std::string colorParamName = "color"; // Check that the parameter is set and retrieve it. // The getQueryParameter function will modify the second parameter, but only if the query // parameter is set. std::string requestColor; if (params->getQueryParameter(colorParamName, requestColor)) { // Check for correct length if (requestColor.length()==6) { bool colorOk = true; // Check that we only have characters within [0-9a-fA-F] for(int i = 1; i < 6 && colorOk; i++) { if (!( (requestColor[i]>='0' && requestColor[i]<='9' ) || (requestColor[i]>='a' && requestColor[i]<='f' ) || (requestColor[i]>='A' && requestColor[i]<='F' ) )) { colorOk = false; } } // If validation was successful, replace the default color if (colorOk) { fillColor = requestColor; } } } // Print the SVG to the response: res->print("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); res->print("<svg id=\"svg1923\" width=\"733\" xmlns=\"http://www.w3.org/2000/svg\" height=\"733\">"); res->print("<circle cy=\"366.5\" cx=\"366.5\" r=\"366.5\"/>"); res->print("<circle cy=\"366.5\" cx=\"366.5\" r=\"336.5\" fill=\"#"); // We insert the color from the parameter here res->printStd(fillColor); res->print("\"/>"); res->print("<path d=\"m325 665c-121-21-194-115-212-233v-8l-25-1-1-18h481c6 13 10 27 13 41 13 94-38 146-114 193-45 23-93 29-142 26z\"/>"); res->print("<path d=\"m372 647c52-6 98-28 138-62 28-25 46-56 51-87 4-20 1-57-5-70l-423-1c-2 56 39 118 74 157 31 34 72 54 116 63 11 2 38 2 49 0z\" fill=\"#871945\"/>"); res->print("<path d=\"m76 342c-13-26-13-57-9-85 6-27 18-52 35-68 21-20 50-23 77-18 15 4 28 12 39 23 18 17 30 40 36 67 4 20 4 41 0 60l-6 21z\"/>"); res->print("<path d=\"m234 323c5-6 6-40 2-58-3-16-4-16-10-10-14 14-38 14-52 0-15-18-12-41 6-55 3-3 5-5 5-6-1-4-22-8-34-7-42 4-57.6 40-66.2 77-3 17-1 53 4 59h145.2z\" fill=\"#fff\"/>"); res->print("<path d=\"m378 343c-2-3-6-20-7-29-5-28-1-57 11-83 15-30 41-52 72-60 29-7 57 0 82 15 26 17 45 49 50 82 2 12 2 33 0 45-1 10-5 26-8 30z\"/>"); res->print("<path d=\"m565 324c4-5 5-34 4-50-2-14-6-24-8-24-1 0-3 2-6 5-17 17-47 13-58-9-7-16-4-31 8-43 4-4 7-8 7-9 0 0-4-2-8-3-51-17-105 20-115 80-3 15 0 43 3 53z\" fill=\"#fff\"/>"); res->print("<path d=\"m504 590s-46 40-105 53c-66 15-114-7-114-7s14-76 93-95c76-18 126 49 126 49z\" fill=\"#f9bedd\"/>"); res->print("</svg>"); } // This is a more generic demo for the query parameters. It makes use of the iterator // interface to access them, which is useful if you do not know the paramter names in // adavance. void handleQueryDemo(HTTPRequest * req, HTTPResponse * res) { // A word of warning: In this example, we use the query parameters and directly print // them into the HTML output. We do this to simplify the demo. NEVER do this in a // real application, as it allows cross-site-scripting. res->setHeader("Content-Type", "text/html"); res->println("<!DOCTYPE html>"); res->println("<html>"); res->println("<head>"); res->println("<title>Query Parameter Demo</title>"); res->println("</head>"); res->println("<body>"); res->println("<p>The following query paramters have been set:</p>"); // Start a table to display the parameters res->println("<table style=\"border:1px solid black collapse;\">"); res->println("<tr><th>Key</th><th>Value</th></tr>"); // Iterate over the parameters. For more information, read about the C++ standard template library, // especially about vectors and iterators. ResourceParameters *params = req->getParams(); for(auto it = params->beginQueryParameters(); it != params->endQueryParameters(); ++it) { res->print("<tr><td>"); // The iterator yields std::pairs of std::strings. The first value contains the parameter key res->printStd((*it).first); res->print("</td><td>"); // and the second value contains the parameter value res->printStd((*it).second); res->println("</td></tr>"); } res->println("</table>"); // You can retrieve the total parameter count from the parameters instance: res->print("<p>There are a total of "); res->print(params->getQueryParameterCount()); res->print(" parameters, with "); res->print(params->getQueryParameterCount(true)); res->println(" unique keys.</p>"); res->println("<p>Go <a href=\"/\">back to main page</a>.</p>"); res->println("</body>"); res->println("</html>"); } // This is a simple handler function that will show the content of URL parameters. // If you call for example /urlparam/foo/bar, you will get the parameter values // "foo" and "bar" provided by the ResourceParameters. void handlePathParam(HTTPRequest * req, HTTPResponse * res) { // Get access to the parameters ResourceParameters * params = req->getParams(); // Set a simple content type res->setHeader("Content-Type", "text/plain"); // The url pattern is: /urlparam/*/* // This will make the content for the first parameter available on index 0, // and the second wildcard as index 1. // getPathParameter will - like getQueryParameter - write the value to the second parameter, // and return true, if the index is valid. Otherwise it returns false and leaves the second // parameter as it is. std::string parameter1, parameter2; // Print the first parameter value if (params->getPathParameter(0, parameter1)) { res->print("Parameter 1: "); res->printStd(parameter1); } res->println(); // Print the second parameter value if (params->getPathParameter(1, parameter2)) { res->print("Parameter 2: "); res->printStd(parameter2); } res->println("\n\nChange the parameters in the URL to see how they get parsed!"); } // For details to this function, see the Static-Page example void handle404(HTTPRequest * req, HTTPResponse * res) { req->discardRequestBody(); res->setStatusCode(404); res->setStatusText("Not Found"); res->setHeader("Content-Type", "text/html"); 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>"); }