Skip to content

Commit

Permalink
Merge pull request #191 from mathieucarbou/middlewares
Browse files Browse the repository at this point in the history
Aligning middleware implementations (cors, auth, logging) with espasyncws and arduino ws
  • Loading branch information
mathieucarbou authored Sep 28, 2024
2 parents cb88011 + 3411f17 commit 0c743f0
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 203 deletions.
126 changes: 49 additions & 77 deletions examples/esp-idf/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const char* app_user = "admin";
const char* app_pass = "admin";
const char* app_name = "Your App";

AuthenticationMiddleware basicAuth(app_user, app_pass, HTTPAuthMethod::BASIC_AUTH, app_name, "You must log in.");
AuthenticationMiddleware digestAuth(app_user, app_pass, HTTPAuthMethod::DIGEST_AUTH, app_name, "You must log in.");
AuthenticationMiddleware basicAuth;
AuthenticationMiddleware digestAuth;

// hostname for mdns (psychic.local)
const char* local_hostname = "psychic";
Expand Down Expand Up @@ -95,10 +95,8 @@ bool connectToWifi()
int numberOfTries = 20;

// Wait for the WiFi event
while (true)
{
switch (WiFi.status())
{
while (true) {
switch (WiFi.status()) {
case WL_NO_SSID_AVAIL:
Serial.println("[WiFi] SSID not found");
break;
Expand Down Expand Up @@ -128,15 +126,12 @@ bool connectToWifi()
}
delay(tryDelay);

if (numberOfTries <= 0)
{
if (numberOfTries <= 0) {
Serial.print("[WiFi] Failed to connect to WiFi!");
// Use disconnect function to force stop trying to connect
WiFi.disconnect();
return false;
}
else
{
} else {
numberOfTries--;
}
}
Expand All @@ -151,51 +146,41 @@ void setup()

// We start by connecting to a WiFi network
// To debug, please enable Core Debug Level to Verbose
if (connectToWifi())
{
if (connectToWifi()) {
// set up our esp32 to listen on the local_hostname.local domain
if (!MDNS.begin(local_hostname))
{
if (!MDNS.begin(local_hostname)) {
Serial.println("Error starting mDNS");
return;
}
MDNS.addService("http", "tcp", 80);

if (!LittleFS.begin())
{
if (!LittleFS.begin()) {
Serial.println("LittleFS Mount Failed. Do Platform -> Build Filesystem Image and Platform -> Upload Filesystem Image from VSCode");
return;
}

// look up our keys?
#ifdef CONFIG_ESP_HTTPS_SERVER_ENABLE
if (app_enable_ssl)
{
if (app_enable_ssl) {
File fp = LittleFS.open("/server.crt");
if (fp)
{
if (fp) {
server_cert = fp.readString();

// Serial.println("Server Cert:");
// Serial.println(server_cert);
}
else
{
} else {
Serial.println("server.pem not found, SSL not available");
app_enable_ssl = false;
}
fp.close();

File fp2 = LittleFS.open("/server.key");
if (fp2)
{
if (fp2) {
server_key = fp2.readString();

// Serial.println("Server Key:");
// Serial.println(server_key);
}
else
{
} else {
Serial.println("server.key not found, SSL not available");
app_enable_ssl = false;
}
Expand All @@ -210,20 +195,30 @@ void setup()
server.ssl_config.httpd.max_uri_handlers = 20; // maximum number of uri handlers (.on() calls)

// do we want secure or not?
if (app_enable_ssl)
{
if (app_enable_ssl) {
server.setCertificate(server_cert.c_str(), server_key.c_str());

// this creates a 2nd server listening on port 80 and redirects all requests HTTPS
PsychicHttpServer* redirectServer = new PsychicHttpServer();
redirectServer->config.ctrl_port = 20424; // just a random port different from the default one
redirectServer->onNotFound([](PsychicRequest* request, PsychicResponse *response)
{
redirectServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
String url = "https://" + request->host() + request->url();
return response->redirect(url.c_str()); });
}
#endif

basicAuth.setUsername(app_user);
basicAuth.setPassword(app_pass);
basicAuth.setRealm(app_name);
basicAuth.setAuthMethod(HTTPAuthMethod::BASIC_AUTH);
basicAuth.setAuthFailureMessage("You must log in.");

digestAuth.setUsername(app_user);
digestAuth.setPassword(app_pass);
digestAuth.setRealm(app_name);
digestAuth.setAuthMethod(HTTPAuthMethod::DIGEST_AUTH);
digestAuth.setAuthFailureMessage("You must log in.");

// serve static files from LittleFS/www on / only to clients on same wifi network
// this is where our /index.html file lives
server.serveStatic("/", LittleFS, "/www/")->addFilter(ON_STA_FILTER);
Expand All @@ -240,16 +235,13 @@ void setup()
server.serveStatic("/myfile.txt", LittleFS, "/custom.txt");

// example callback everytime a connection is opened
server.onOpen([](PsychicClient* client)
{ Serial.printf("[http] connection #%u connected from %s\n", client->socket(), client->localIP().toString().c_str()); });
server.onOpen([](PsychicClient* client) { Serial.printf("[http] connection #%u connected from %s\n", client->socket(), client->localIP().toString().c_str()); });

// example callback everytime a connection is closed
server.onClose([](PsychicClient* client)
{ Serial.printf("[http] connection #%u closed from %s\n", client->socket(), client->localIP().toString().c_str()); });
server.onClose([](PsychicClient* client) { Serial.printf("[http] connection #%u closed from %s\n", client->socket(), client->localIP().toString().c_str()); });

// api - json message passed in as post body
server.on("/api", HTTP_POST, [](PsychicRequest* request, PsychicResponse *response)
{
server.on("/api", HTTP_POST, [](PsychicRequest* request, PsychicResponse* response) {
//load our JSON request
JsonDocument json;
String body = request->body();
Expand Down Expand Up @@ -284,14 +276,12 @@ void setup()
return response->send(200, "application/json", jsonBuffer.c_str()); });

// api - parameters passed in via query eg. /api/endpoint?foo=bar
server.on("/ip", HTTP_GET, [](PsychicRequest* request, PsychicResponse *response)
{
server.on("/ip", HTTP_GET, [](PsychicRequest* request, PsychicResponse* response) {
String output = "Your IP is: " + request->client()->remoteIP().toString();
return response->send(output.c_str()); });

// api - parameters passed in via query eg. /api/endpoint?foo=bar
server.on("/api", HTTP_GET, [](PsychicRequest* request, PsychicResponse *response)
{
server.on("/api", HTTP_GET, [](PsychicRequest* request, PsychicResponse* response) {
//create a response object
JsonDocument output;
output["msg"] = "status";
Expand All @@ -311,22 +301,16 @@ void setup()
return response->send(200, "application/json", jsonBuffer.c_str()); });

// how to redirect a request
server.on("/redirect", HTTP_GET, [](PsychicRequest* request, PsychicResponse *response)
{ return response->redirect("/alien.png"); });
server.on("/redirect", HTTP_GET, [](PsychicRequest* request, PsychicResponse* response) { return response->redirect("/alien.png"); });

// how to do basic auth
server.on("/auth-basic", HTTP_GET, [](PsychicRequest* request, PsychicResponse *response)
{
return response->send("Auth Basic Success!"); })->addMiddleware(&basicAuth);
server.on("/auth-basic", HTTP_GET, [](PsychicRequest* request, PsychicResponse* response) { return response->send("Auth Basic Success!"); })->addMiddleware(&basicAuth);

// how to do digest auth
server.on("/auth-digest", HTTP_GET, [](PsychicRequest* request, PsychicResponse *response)
{
return response->send("Auth Digest Success!"); })->addMiddleware(&digestAuth);
server.on("/auth-digest", HTTP_GET, [](PsychicRequest* request, PsychicResponse* response) { return response->send("Auth Digest Success!"); })->addMiddleware(&digestAuth);

// example of getting / setting cookies
server.on("/cookies", HTTP_GET, [](PsychicRequest* request, PsychicResponse *response)
{
server.on("/cookies", HTTP_GET, [](PsychicRequest* request, PsychicResponse* response) {
int counter = 0;
char cookie[14];
size_t size = 14;
Expand All @@ -343,22 +327,19 @@ void setup()
return response->send(); });

// example of getting POST variables
server.on("/post", HTTP_POST, [](PsychicRequest* request, PsychicResponse *response)
{
server.on("/post", HTTP_POST, [](PsychicRequest* request, PsychicResponse* response) {
String output;
output += "Param 1: " + request->getParam("param1")->value() + "<br/>\n";
output += "Param 2: " + request->getParam("param2")->value() + "<br/>\n";

return response->send(output.c_str()); });

// you can set up a custom 404 handler.
server.onNotFound([](PsychicRequest* request, PsychicResponse *response)
{ return response->send(404, "text/html", "Custom 404 Handler"); });
server.onNotFound([](PsychicRequest* request, PsychicResponse* response) { return response->send(404, "text/html", "Custom 404 Handler"); });

// handle a very basic upload as post body
PsychicUploadHandler* uploadHandler = new PsychicUploadHandler();
uploadHandler->onUpload([](PsychicRequest* request, const String& filename, uint64_t index, uint8_t* data, size_t len, bool last)
{
uploadHandler->onUpload([](PsychicRequest* request, const String& filename, uint64_t index, uint8_t* data, size_t len, bool last) {
File file;
String path = "/www/" + filename;

Expand Down Expand Up @@ -386,8 +367,7 @@ void setup()
return ESP_OK; });

// gets called after upload has been handled
uploadHandler->onRequest([](PsychicRequest* request, PsychicResponse *response)
{
uploadHandler->onRequest([](PsychicRequest* request, PsychicResponse* response) {
String url = "/" + request->getFilename();
String output = "<a href=\"" + url + "\">" + url + "</a>";

Expand All @@ -398,8 +378,7 @@ void setup()

// a little bit more complicated multipart form
PsychicUploadHandler* multipartHandler = new PsychicUploadHandler();
multipartHandler->onUpload([](PsychicRequest* request, const String& filename, uint64_t index, uint8_t* data, size_t len, bool last)
{
multipartHandler->onUpload([](PsychicRequest* request, const String& filename, uint64_t index, uint8_t* data, size_t len, bool last) {
File file;
String path = "/www/" + filename;

Expand Down Expand Up @@ -427,8 +406,7 @@ void setup()
return ESP_OK; });

// gets called after upload has been handled
multipartHandler->onRequest([](PsychicRequest* request, PsychicResponse *response)
{
multipartHandler->onRequest([](PsychicRequest* request, PsychicResponse* response) {
PsychicWebParameter *file = request->getParam("file_upload");

String url = "/" + file->value();
Expand All @@ -445,25 +423,20 @@ void setup()
server.on("/multipart", HTTP_POST, multipartHandler);

// a websocket echo server
websocketHandler.onOpen([](PsychicWebSocketClient* client)
{
websocketHandler.onOpen([](PsychicWebSocketClient* client) {
Serial.printf("[socket] connection #%u connected from %s\n", client->socket(), client->localIP().toString().c_str());
client->sendMessage("Hello!"); });
websocketHandler.onFrame([](PsychicWebSocketRequest* request, httpd_ws_frame* frame)
{
websocketHandler.onFrame([](PsychicWebSocketRequest* request, httpd_ws_frame* frame) {
Serial.printf("[socket] #%d sent: %s\n", request->client()->socket(), (char *)frame->payload);
return request->reply(frame); });
websocketHandler.onClose([](PsychicWebSocketClient* client)
{ Serial.printf("[socket] connection #%u closed from %s\n", client->socket(), client->localIP().toString().c_str()); });
websocketHandler.onClose([](PsychicWebSocketClient* client) { Serial.printf("[socket] connection #%u closed from %s\n", client->socket(), client->localIP().toString().c_str()); });
server.on("/ws", &websocketHandler);

// EventSource server
eventSource.onOpen([](PsychicEventSourceClient* client)
{
eventSource.onOpen([](PsychicEventSourceClient* client) {
Serial.printf("[eventsource] connection #%u connected from %s\n", client->socket(), client->localIP().toString().c_str());
client->send("Hello user!", NULL, millis(), 1000); });
eventSource.onClose([](PsychicEventSourceClient* client)
{ Serial.printf("[eventsource] connection #%u closed from %s\n", client->socket(), client->localIP().toString().c_str()); });
eventSource.onClose([](PsychicEventSourceClient* client) { Serial.printf("[eventsource] connection #%u closed from %s\n", client->socket(), client->localIP().toString().c_str()); });
server.on("/events", &eventSource);
}
}
Expand All @@ -473,8 +446,7 @@ char output[60];

void loop()
{
if (millis() - lastUpdate > 2000)
{
if (millis() - lastUpdate > 2000) {
sprintf(output, "Millis: %lu\n", millis());
websocketHandler.sendAll(output);

Expand Down
20 changes: 17 additions & 3 deletions examples/platformio/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ const char* app_user = "admin";
const char* app_pass = "admin";
const char* app_name = "Your App";

LoggingMiddleware loggingMiddleware(Serial);
AuthenticationMiddleware basicAuth(app_user, app_pass, HTTPAuthMethod::BASIC_AUTH, app_name, "You must log in.");
AuthenticationMiddleware digestAuth(app_user, app_pass, HTTPAuthMethod::DIGEST_AUTH, app_name, "You must log in.");
LoggingMiddleware loggingMiddleware;
AuthenticationMiddleware basicAuth;
AuthenticationMiddleware digestAuth;

// hostname for mdns (psychic.local)
const char* local_hostname = "psychic";
Expand Down Expand Up @@ -330,6 +330,20 @@ void setup()

DefaultHeaders::Instance().addHeader("Server", "PsychicHttp");

loggingMiddleware.setOutput(Serial);

basicAuth.setUsername(app_user);
basicAuth.setPassword(app_pass);
basicAuth.setRealm(app_name);
basicAuth.setAuthMethod(HTTPAuthMethod::BASIC_AUTH);
basicAuth.setAuthFailureMessage("You must log in.");

digestAuth.setUsername(app_user);
digestAuth.setPassword(app_pass);
digestAuth.setRealm(app_name);
digestAuth.setAuthMethod(HTTPAuthMethod::DIGEST_AUTH);
digestAuth.setAuthFailureMessage("You must log in.");

server.addMiddleware(&loggingMiddleware);
// this will send CORS headers on every HTTP_OPTIONS request that contains the Origin: header
server.addMiddleware(&corsMiddleware);
Expand Down
Loading

0 comments on commit 0c743f0

Please sign in to comment.