lasselukkari / aWOT

Arduino web server library.
MIT License
283 stars 41 forks source link

Member functions as Middleware* #134

Closed kine90 closed 1 year ago

kine90 commented 2 years ago

Do somebody ever tried to build a library over this server? Since "ESPAsyncWiFiManager" is not working over Ethernet, I am trying to build my library for a Webmanager which works over Ethernet, but I can´t figure out how to pass member functions of my EthWebManager class as middlewares.

I am trying with std::bind, here is a code snippet:

void EthWebManager::auth(Request &req, Response &res) { char * authHeader = req.get("Authorization");

if (!str_iseq(authHeader, encoded_login1.c_str()) && !str_iseq(authHeader, encoded_login2.c_str())) { res.set("WWW-Authenticate", "Basic realm=\"Secret Area\""); res.sendStatus(401); res.end(); DEBUG_WM(F("Unauthenticated")); } }

void EthWebManager::handleRoot(Request &req, Response &res) { String page = FPSTR(WFM_HTTP_HEAD); page.replace("{v}", "Home"); page += FPSTR(HTTP_SCRIPT); page += FPSTR(HTTP_STYLE); page += FPSTR(HTTP_HEAD_END); page += F("

EthWebManager

"); page += FPSTR(HTTP_PORTAL_OPTIONS); page += FPSTR(HTTP_END); res.set("Content-Type", "text/html"); res.print(page); }

void EthWebManager::startEthManager() { server->begin(); delay(500); mainapp.header("Authorization", authBuffer, 200); mainapp.use(std::bind(&EthWebManager::auth, this, std::placeholders::_1, std::placeholders::_2)); auto callable = std::bind(&EthWebManager::handleRoot, this, std::placeholders::_1, std::placeholders::_2); mainapp.get("/", callable ); }

But I keep getting these errors:

lib\EthWebManager\src\EthWebManager.cpp: In member function 'void EthWebManager::startEthManager()': lib\EthWebManager\src\EthWebManager.cpp:361:98: error: no matching function for call to 'awot::Application::use(std::_Bind_helper<false, void (EthWebManager::)(awot::Request&, awot::Response&), EthWebManager, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type)' mainapp.use(std::bind(&EthWebManager::auth, this, std::placeholders::_1, std::placeholders::_2)); ^ In file included from lib\EthWebManager\src\EthWebManager.h:22:0, from lib\EthWebManager\src\EthWebManager.cpp:14: .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:322:8: note: candidate: void awot::Application::use(const char, awot::Router) void use(const char path, Router router); ^ .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:322:8: note: candidate expects 2 arguments, 1 provided .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:323:8: note: candidate: void awot::Application::use(awot::Router) void use(Router router); ^ .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:323:8: note: no known conversion for argument 1 from 'std::_Bind_helper<false, void (EthWebManager::)(awot::Request&, awot::Response&), EthWebManager, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type {aka std::_Bind<std::_Mem_fn<void (EthWebManager::)(awot::Request&, awot::Response&)>(EthWebManager, std::_Placeholder<1>, std::_Placeholder<2>)>}' to 'awot::Router' .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:324:8: note: candidate: void awot::Application::use(const char, void ()(awot::Request&, awot::Response&)) void use(const char path, Router::Middleware middleware); ^ .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:324:8: note: candidate expects 2 arguments, 1 provided .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:325:8: note: candidate: void awot::Application::use(void ()(awot::Request&, awot::Response&)) void use(Router::Middleware middleware); ^ .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:325:8: note: no known conversion for argument 1 from 'std::_Bind_helper<false, void (EthWebManager::)(awot::Request&, awot::Response&), EthWebManager, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type {aka std::_Bind<std::_Mem_fn<void (EthWebManager::)(awot::Request&, awot::Response&)>(EthWebManager, std::_Placeholder<1>, std::_Placeholder<2>)>}' to 'void ()(awot::Request&, awot::Response&)' lib\EthWebManager\src\EthWebManager.cpp:363:29: error: no matching function for call to 'awot::Application::get(const char [2], std::_Bind<std::_Mem_fn<void (EthWebManager::)(awot::Request&, awot::Response&)>(EthWebManager, std::_Placeholder<1>, std::_Placeholder<2>)>&)' mainapp.get("/", callable ); / ^ In file included from lib\EthWebManager\src\EthWebManager.h:22:0, from lib\EthWebManager\src\EthWebManager.cpp:14: .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:300:8: note: candidate: void awot::Application::get(const char, void ()(awot::Request&, awot::Response&)) void get(const char path, Router::Middleware middleware); ^ .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:300:8: note: no known conversion for argument 2 from 'std::_Bind<std::_Mem_fn<void (EthWebManager::)(awot::Request&, awot::Response&)>(EthWebManager, std::_Placeholder<1>, std::_Placeholder<2>)>' to 'void ()(awot::Request&, awot::Response&)'
.pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:301:8: note: candidate: void awot::Application::get(void ()(awot::Request&, awot::Response&)) void get(Router::Middleware middleware); ^ .pio\libdeps\m5stack-core-esp32\aWOT\src/aWOT.h:301:8: note: candidate expects 1 argument, 2 provided *** [.pio\build\m5stack-core-esp32\lib4c6\EthWebManager\EthWebManager.cpp.o] Error 1

lasselukkari commented 2 years ago

Member functions as middleware are currently not supported as the compiler for avr microcontrollers does not support them. I already created a branch with the support but never merged it because it would mean it would not work with the old Arduinos. You can see the branch here: https://github.com/lasselukkari/aWOT/tree/std-function-middleware.

I may add this functionality to the version 4 of the library. I'm planning to make this with some checks for the environment. Contributions are really welcome.

lasselukkari commented 2 years ago

You should be able to get this done by wrapping the call to the member function with a middleware function but you will need to create an instance of the class in the library code. This may not the most optimal solution but it should work.

kine90 commented 2 years ago

@lasselukkari thanks a lot for your quick answer and for sharing this library! I have been able to solve the problem using the old branch named "std-function-middleware" (I had to add the line#include <functional> in the header file aWOT.h). This way the return type of the std::bind function is accepted as middleware and everything works like a charm. What about moving this feature in the main branch?

lasselukkari commented 2 years ago

I will add this to the next major version 4 of the library as it will introduce backwards incompatible changes. How ever this will take some time as I'm currently concentrating on making sawdust with a 5-axis cnc machine. Most likely this will land to the master branch with some other changes at the end of the year.

lasselukkari commented 1 year ago

Been making a lot of sawdust... The functionality is finally here. I made it so that it's still backwards compatible. I'll merge and publish it soon.