ESP32_ChinaDieselHeater_Con.../lib/esp32_https_server-master/examples/Parameters/Parameters.ino

355 lines
14 KiB
C++

/**
* 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>");
}