From 48f39b5f025b1bc4efa61d0101e8a3951ee1bb99 Mon Sep 17 00:00:00 2001 From: Slavey Karadzhov Date: Wed, 21 Jul 2021 16:33:19 +0200 Subject: [PATCH] Moved the HttpServer Plugins demo to a separate sample application. --- .../Http/Resource/Content/DecoderContent.h | 37 ----- samples/HttpServer_Plugins/.cproject | 151 ++++++++++++++++++ samples/HttpServer_Plugins/.project | 28 ++++ samples/HttpServer_Plugins/Makefile | 9 ++ samples/HttpServer_Plugins/README.rst | 10 ++ .../HttpServer_Plugins/app/application.cpp | 92 +++++++++++ samples/HttpServer_Plugins/component.mk | 1 + .../include/ContentDecoderPlugin.h | 82 ++++++++++ .../HttpServer_WebSockets/app/application.cpp | 16 -- 9 files changed, 373 insertions(+), 53 deletions(-) delete mode 100644 Sming/Components/Network/src/Network/Http/Resource/Content/DecoderContent.h create mode 100644 samples/HttpServer_Plugins/.cproject create mode 100644 samples/HttpServer_Plugins/.project create mode 100644 samples/HttpServer_Plugins/Makefile create mode 100644 samples/HttpServer_Plugins/README.rst create mode 100644 samples/HttpServer_Plugins/app/application.cpp create mode 100644 samples/HttpServer_Plugins/component.mk create mode 100644 samples/HttpServer_Plugins/include/ContentDecoderPlugin.h diff --git a/Sming/Components/Network/src/Network/Http/Resource/Content/DecoderContent.h b/Sming/Components/Network/src/Network/Http/Resource/Content/DecoderContent.h deleted file mode 100644 index 93763be187..0000000000 --- a/Sming/Components/Network/src/Network/Http/Resource/Content/DecoderContent.h +++ /dev/null @@ -1,37 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * - * @author: 2021 - Slavey Karadzhov - * - ****/ - -#pragma once - -#include "../HttpResourcePlugin.h" -#include - -class DecoderContent : public HttpResourcePlugin -{ - bool registerPlugin(HttpEventedResource& resource) override - { - // Check if the provided content is encoded in some way - return resource.addEvent( - HttpEventedResource::EVENT_BODY, - [](HttpServerConnection& connection, char** at, int* length) { - auto request = connection.getRequest(); - if(request->headers[HTTP_HEADER_CONTENT_ENCODING] == "test") { - char* data = *at; - for(unsigned i = 0; i < *length; i++) { - data[i]++; - } - } - - return true; - }, - 1); - } -}; diff --git a/samples/HttpServer_Plugins/.cproject b/samples/HttpServer_Plugins/.cproject new file mode 100644 index 0000000000..e6469c9e2f --- /dev/null +++ b/samples/HttpServer_Plugins/.cproject @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + -f ${ProjDirPath}/Makefile + all + true + true + true + + + make + -f ${ProjDirPath}/Makefile + clean + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flash + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashonefile + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashinit + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashboot + true + true + true + + + make + -f ${ProjDirPath}/Makefile + rebuild + true + true + true + + + + + + + + + + + + + + + + + + + + diff --git a/samples/HttpServer_Plugins/.project b/samples/HttpServer_Plugins/.project new file mode 100644 index 0000000000..67c872c77a --- /dev/null +++ b/samples/HttpServer_Plugins/.project @@ -0,0 +1,28 @@ + + + HttpServer_Plugins + + + SmingFramework + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/samples/HttpServer_Plugins/Makefile b/samples/HttpServer_Plugins/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/samples/HttpServer_Plugins/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/samples/HttpServer_Plugins/README.rst b/samples/HttpServer_Plugins/README.rst new file mode 100644 index 0000000000..e694a3db72 --- /dev/null +++ b/samples/HttpServer_Plugins/README.rst @@ -0,0 +1,10 @@ +HttpServer Plugins +===================== + +Simple example that demonstrate extending the HttpServer functionality with additional plugins. +Using such examples one can add: + + - URL Rewriting + - Authentication. Sming has already existing plugins for Basic Authentication, IP Limiting + - Content extracting/processing. For example a gzip decoder plugin can be implemented. + diff --git a/samples/HttpServer_Plugins/app/application.cpp b/samples/HttpServer_Plugins/app/application.cpp new file mode 100644 index 0000000000..4398501e10 --- /dev/null +++ b/samples/HttpServer_Plugins/app/application.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include "ContentDecoderPlugin.h" + +// If you want, you can define WiFi settings globally in Eclipse Environment Variables +#ifndef WIFI_SSID +#define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here +#define WIFI_PWD "PleaseEnterPass" +#endif + +namespace +{ +HttpServer server; + +void echoContentBody(HttpRequest& request, HttpResponse& response) +{ + auto body = request.getBody(); + debug_d("Got content (after modifications): %s", body.c_str()); + + response.headers[HTTP_HEADER_CONTENT_TYPE] = request.headers[HTTP_HEADER_CONTENT_TYPE]; + response.sendString(body); +} + +void startWebServer() +{ + server.listen(80); + server.paths.set("/", echoContentBody); + server.paths.setDefault(echoContentBody); + + /* + * By default the server does not store the incoming information. + * There has to be either a plugin that does this or a body parser. + * In this sample we use a body parser that stores the information into memory. + */ + server.setBodyParser(MIME_FORM_URL_ENCODED, bodyToStringParser); + + // Here we use a simple plugin that protects the access to a resource using HTTP Basic Authentication + auto pluginBasicAuth = new ResourceBasicAuth("realm", "username", "password"); + // You can add one or more authentication methods or other plugins... + server.paths.set("/auth", echoContentBody, pluginBasicAuth); + + /* + * The plugins will be registered in the order in which they are provided. + * For example in the command below the IP restriction plugin will be registered first + * followed by the basic authentication plugin. + * You can run the following curl command to test these plugins: + * + * curl -vvv http://username:password@192.168.13.10/ip-n-auth + * + * make sure to replace the IP address with the IP address of your HttpServer + */ + server.paths.set("/ip-n-auth", echoContentBody, + new ResourceIpAuth(IpAddress("192.168.13.0"), IpAddress("255.255.255.0")), pluginBasicAuth); + + /* + * This content coming to this resource is modified on the fly + * using our ContentDecoderPlugin. See the source code of ContentDecoderPlugin + * to get an idea how to create your own plugin. + * You can run the following curl command to test this plugin: + * + * curl -vvv http://username@192.168.13.10/test -d "text=1" -H "Content-Encoding: test" + * + * make sure to replace the IP address with the IP address of your HttpServer + */ + server.paths.set("/test", echoContentBody, new ContentDecoderPlugin()); + + Serial.println(F("\r\n=== WEB SERVER STARTED ===")); + Serial.println(WifiStation.getIP()); + Serial.println(F("==============================\r\n")); +} + +// Will be called when WiFi station becomes fully operational +void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) +{ + startWebServer(); +} + +} // namespace + +void init() +{ + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(true); // Enable debug output to serial + + WifiStation.enable(true); + WifiStation.config(WIFI_SSID, WIFI_PWD); + WifiAccessPoint.enable(false); + + // Run our method when station was connected to AP + WifiEvents.onStationGotIP(gotIP); +} diff --git a/samples/HttpServer_Plugins/component.mk b/samples/HttpServer_Plugins/component.mk new file mode 100644 index 0000000000..6a0c019953 --- /dev/null +++ b/samples/HttpServer_Plugins/component.mk @@ -0,0 +1 @@ +HWCONFIG := standard diff --git a/samples/HttpServer_Plugins/include/ContentDecoderPlugin.h b/samples/HttpServer_Plugins/include/ContentDecoderPlugin.h new file mode 100644 index 0000000000..561ebff151 --- /dev/null +++ b/samples/HttpServer_Plugins/include/ContentDecoderPlugin.h @@ -0,0 +1,82 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * + * @author: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include +#include + +namespace +{ +constexpr char ENCODING_NAME[] = "test"; +} + +class ContentDecoderPlugin : public HttpResourcePlugin +{ +public: + bool registerPlugin(HttpEventedResource& resource) override + { + // We register two events - one is executed as soon as the client request comes to the server + // and in it we add a header to the response that inform the http client that + // we support our own content encoding called "test" + resource.addEvent( + HttpEventedResource::EVENT_URL, // event to listen to + HttpEventedResource::EventCallback(&ContentDecoderPlugin::onUrl, this), // callback to execute + 1); // priority to use. 1 means that this callback will be called BEFORE the normal onUrl callback + + resource.addEvent(HttpEventedResource::EVENT_HEADERS, + HttpEventedResource::EventCallback(&ContentDecoderPlugin::onHeaders, this), + 1); // + + resource.addEvent(HttpEventedResource::EVENT_BODY, + HttpEventedResource::EventCallback(&ContentDecoderPlugin::onBody, this), + 1); // + + return true; + } + + bool onHeaders(HttpServerConnection& connection, char** at, int* length) + { + auto request = connection.getRequest(); + if(request->headers[HTTP_HEADER_CONTENT_ENCODING] == ENCODING_NAME) { + auto response = connection.getResponse(); + response->headers[HTTP_HEADER_CONTENT_ENCODING] = ENCODING_NAME; + } + + return true; + } + + bool onUrl(HttpServerConnection& connection, char** at, int* length) + { + auto response = connection.getResponse(); + String content = response->headers["Accept-Encoding"]; + if(content.length() > 0) { + content += ", "; + } + content += "test"; + response->headers["Accept-Encoding"] = content; + + return true; + } + + bool onBody(HttpServerConnection& connection, char** at, int* length) + { + auto request = connection.getRequest(); + if(request->headers[HTTP_HEADER_CONTENT_ENCODING] == ENCODING_NAME) { + char* data = *at; + for(unsigned i = 0; i < *length; i++) { + data[i]++; + } + } + + return true; + } +}; diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index 1e1ff857f2..02e46a89e3 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -1,7 +1,5 @@ #include #include -#include -#include #include "CUserData.h" // If you want, you can define WiFi settings globally in Eclipse Environment Variables @@ -97,19 +95,12 @@ void wsDisconnected(WebsocketConnection& socket) socket.broadcast(message); } -void onTest(HttpRequest& request, HttpResponse& response) -{ - debug_d("Got content: %s", request.getBody().c_str()); -} - void startWebServer() { server.listen(80); server.paths.set("/", onIndex); server.paths.setDefault(onFile); - server.setBodyParser(MIME_FORM_URL_ENCODED, bodyToStringParser); - // Web Sockets configuration auto wsResource = new WebsocketResource(); wsResource->setConnectionHandler(wsConnected); @@ -117,14 +108,7 @@ void startWebServer() wsResource->setBinaryHandler(wsBinaryReceived); wsResource->setDisconnectionHandler(wsDisconnected); - auto pluginBasicAuth = new ResourceBasicAuth("realm", "username", "password"); server.paths.set("/ws", wsResource); - // You can add one or more authentication methods or other plugins... - server.paths.set("/protected", onIndex, pluginBasicAuth); - server.paths.set("/ip", onIndex, new ResourceIpAuth(IpAddress("192.168.13.0"), IpAddress("255.255.255.0")), - pluginBasicAuth); - - server.paths.set("/test", onTest, new DecoderContent()); Serial.println(F("\r\n=== WEB SERVER STARTED ===")); Serial.println(WifiStation.getIP());