ESP32_ChinaDieselHeater_Con.../lib/esp32_https_server-master/examples/Parameter-Validation/Parameter-Validation.ino

275 lines
9.3 KiB
C++

/**
* Example for the ESP32 HTTP(S) Webserver
*
* IMPORTANT NOTE:
* To run this script, you 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:
* - Shows you a page with some LEDs and allow you to turn them on or off
* Parameters for the URLs are checked, so that you cannot address non-existing objects
* - 404 for everything else
* If you want to see the LEDs, connect them to GPIOs 33 (red), 25 (yellow), 26 (green)
* and 27 (blue).
*/
// 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>
// We use strings
#include <string>
// Includes for the server
#include <HTTPSServer.hpp>
#include <SSLCert.hpp>
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>
#include <ValidatorFunctions.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);
// Root node, will show the LEDs that are available
void handleRoot(HTTPRequest * req, HTTPResponse * res);
// Node to switch an LED on or off
void handleSwitch(HTTPRequest * req, HTTPResponse * res);
// Validation function for the LED ID and state, explanation follows below.
bool validateLEDState(std::string s);
bool validateLEDID(std::string s);
// Default handler for resources that do not exist
void handle404(HTTPRequest * req, HTTPResponse * res);
// A class that defines an LED
class LED {
public:
/** Name for the LED */
const std::string _name;
/** Pin that it's connected to */
const uint8_t _pin;
/** Current state */
bool _on;
/** Constructor */
LED(const std::string name, uint8_t pin): _name(name), _pin(pin) {
_on = false;
pinMode(pin, OUTPUT);
}
/** Method to turn the led on or of */
void setOn(bool on) {
digitalWrite(_pin,on?HIGH:LOW);
_on=on;
}
};
// We create some LEDs:
#define LEDCOUNT 4
LED myLEDs[LEDCOUNT] = {
LED("Red LED", 33),
LED("Yellow LED", 25),
LED("Green LED", 26),
LED("Blue LED", 27)
};
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());
// We create a node for the main page of the server, available via get
ResourceNode * nodeRoot = new ResourceNode("/", "GET", &handleRoot);
// This node will turn an LED on or of. It has two parameters:
// 1) The ID of the LED (0..LEDCOUNT)
// 2) The new state (0..1)
// For more information on path parameters in general, see the Parameters example.
ResourceNode * nodeSwitch = new ResourceNode("/led/*/*", "POST", &handleSwitch);
// We want to use parameter validation. The ResourceNode class provides the method
// addPathParamValidator() for that. This method takes two parameters:
// 1) The index of the parameter that you want to validate, so for the first wildcard
// in the route pattern that has been specified above, it's 0, and for the second
// parameter it's 1.
// 2) A function pointer that takes an std::string as parameter and returns a bool.
// That bool should be true if the parameter is considered valid.
// All those functions are called in the order in that they have been added. So if
// you want check if a parameter is an integer and then do some calculation with it,
// make sure to add the integer-check first and the other function later.
//
// If any of the functions returns false, the URL is considered to be invalid completely.
// In this case, the server will return with a static 400 Bad Request response.
//
// For convenience, the ValidatorFunctions.hpp include file already provides some useful
// and common checks (integer, non-empty, ...). Have a look at it before you start
// implementing your own checks to save time!
// First we will take care of the LED ID. This ID should be...
// ... an unsigned integer ...
nodeSwitch->addPathParamValidator(0, &validateUnsignedInteger);
// ... and within the range of known IDs.
// We can treat the parameter safely as integer in this validator, as all validators
// are executed in order and validateUnsignedInteger has been run before.
nodeSwitch->addPathParamValidator(0, &validateLEDID);
// The second parameter should either be 0 or 1. We use our custom validateLEDState() validator for this:
nodeSwitch->addPathParamValidator(1, &validateLEDState);
// Not found node
ResourceNode * node404 = new ResourceNode("", "GET", &handle404);
// Add the root node to the server
secureServer.registerNode(nodeRoot);
// And the switch node
secureServer.registerNode(nodeSwitch);
// 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><head><style>");
res->println("* {font-family: sans-serif; font-size:12px}");
res->println("form.on {background: #ffffcc;color:black;}");
res->println("form.off {background: #404040;color:white;}");
res->println("</style><title>Parameter Validation Example</title></head>");
res->println("<body>");
// Iterate over the LEDs.
for(int id = 0; id < LEDCOUNT; id++) {
LED * led = &myLEDs[id];
res->print(
"<form "
"style=\"border:1px solid black;padding:10px;width:300px;margin:10px;float:left\" "
"method=\"post\" "
"class=\"");
res->print(led->_on ? "on" : "off");
res->print(
"\" "
"action=\"/led/"
);
res->print(id);
res->print("/");
res->print(led->_on ? 0 : 1);
res->print(
"\">"
"<p style=\"text-align:center;font-size:16px;\">"
);
res->printStd(led->_name);
res->print("</p><button type=\"submit\">Turn ");
res->print(led->_on ? "off" : "on");
res->print("</button></form>");
}
res->print(
"<form method=\"post\" action=\"/led/foobar/1\" style=\"clear:both\">"
"<p>To see that the validator functions are working as expected, you can e.g. call <button type=\"submit\">POST /led/foobar/1</button>.</p>"
"</form>"
"</body>"
"</html>"
);
}
// This is the handler for our post callback. We can work with the parameters without further
// validation, as the server assures this function only gets called if the validation succeeded.
void handleSwitch(HTTPRequest * req, HTTPResponse * res) {
// POST, so drain the input, if any
req->discardRequestBody();
// Get access to the parameters
ResourceParameters * params = req->getParams();
// Get the LED that is requested.
// Note that we can call stoi safely without further validation, as we
// defined that is has to be an unsigned integer and must not be >LEDCOUNT-1
LED * led = &myLEDs[std::stoi(params->getPathParameter(0))];
// Set the state of the LED. The value of the parameter can only be "0" or "1" here,
// otherwise the server would not have called the handler.
led->setOn(params->getPathParameter(1)!="0");
// Redirect the user to the main page
res->setStatusCode(303);
// This should make the browser do a GET /
res->setStatusText("See Other");
res->setHeader("Location", "/");
res->println("Redirecting...");
}
// This function is the validator for the second parameter of the POST /led route.
// It accepts only the strings "0" (off) and "1" (on)
bool validateLEDState(std::string s) {
return s == "0" || s == "1";
}
// This function is a validator for the first parameter of the POST /led route.
// We did check before that the parameter is an integer, now we check its range.
bool validateLEDID(std::string s) {
uint32_t id = std::stoul(s);
return id < LEDCOUNT;
}
// 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>");
}