Skip to content

How to pass a object member function to ResourceNode constructor? #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
marfanjr opened this issue Dec 6, 2020 · 4 comments
Open

How to pass a object member function to ResourceNode constructor? #105

marfanjr opened this issue Dec 6, 2020 · 4 comments

Comments

@marfanjr
Copy link

marfanjr commented Dec 6, 2020

I need to register a node callback with a object member function
I created a class to hold all my https request callbacks functions and I want to pass those functions to ResourceNode constructor and register in my server.

Some of my files

https_handler.h

#ifndef HTTPS_HANDLER_H
#define HTTPS_HANDLER_H
#include "Arduino.h"
#include <HTTPSServer.hpp>
#include "SSLCert.hpp"
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>
using namespace httpsserver;
class HttpsHandler {
  public:
    HttpsHandler();
    ~HttpsHandler();
    void root(HTTPRequest * req, HTTPResponse * res);
  private:
};
#endif

https_handler.cpp

#include "https_handler.h"

void HttpsHandler::root(HTTPRequest * req, HTTPResponse * res) {
	// We want to deliver an HTML page, so we set the content type
	res->setHeader("Content-Type", "text/html");
	// The response implements the Print interface, so you can use it just like
	// you would write to Serial etc.
	res->println("<!DOCTYPE html>");
	res->println("<html>");
	res->println("<head><title>Hello World!</title></head>");
	res->println("<body>");
	res->println("<h1>Hello World!</h1>");
	res->print("<p>... from your ESP32!</p>");
	res->println("</body>");
	res->println("</html>");
}

my_server.h

#ifndef MY_SERVER_H
#define MY_SERVER_H

#include "../ssl_certificate/cert.h"
#include "../ssl_certificate/private_key.h"
#include "handlers/https_handler.h"
#include <HTTPSServer.hpp>
#include "SSLCert.hpp"
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>

using namespace httpsserver;

class MyServer {
  public:
    MyServer();
    ~MyServer();
    void setup();
    void loop();
  private:
    SSLCert cert = SSLCert(
        example_crt_DER,     // DER-formatted certificate data
        example_crt_DER_len, // length of the certificate data
        example_key_DER,     // private key for that certificate
        example_key_DER_len  // Length of the private key
    );
    HTTPSServer secureServer = HTTPSServer(&cert);
    HttpsHandler *handler;
    void configureNodes();
};
#endif

my_server.cpp

#include "my_server.h"

MyServer::MyServer(/* args */) { }

MyServer::~MyServer() { }

void MyServer::setup() {
  Serial.println("MyServer::start");
  secureServer.start();
  configureNodes();
};

void MyServer::loop() {
  secureServer.loop();
}


void MyServer::configureNodes() {
  ResourceNode * nodeRoot = new ResourceNode("/", "GET", &HttpsHandler::root);
  secureServer.registerNode(nodeRoot);
}

platformio.ini

[env:development]
platform = espressif32@2.1.0
board = esp32doit-devkit-v1
framework = arduino
upload_speed = 115200
board_build.flash_mode = dio
build_flags =
  -DHTTPS_LOGLEVEL=2
  -DHTTPS_LOGTIMESTAMP
  -DHTTPS_DISABLE_SELFSIGNING
lib_deps =
  fhessel/esp32_https_server

Here the error logs

src/system/communication/protocols/HTTPS/my_server.cpp:23:77: error: no matching function for call to 'httpsserver::ResourceNode::ResourceNode(const char [2], const char [4], void (HttpsHandler::*)(httpsserver::HTTPRequest*, httpsserver::HTTPResponse*))'
   ResourceNode * nodeRoot = new ResourceNode("/", "GET", &HttpsHandler::root);
                                                                             ^
In file included from .pio/libdeps/esp01_1m/esp32_https_server/src/HTTPServer.hpp:20:0,
                 from .pio/libdeps/esp01_1m/esp32_https_server/src/HTTPSServer.hpp:15,
                 from src/system/communication/protocols/HTTPS/handlers/https_handler.h:4,
                 from src/system/communication/protocols/HTTPS/my_server.h:6,
                 from src/system/communication/protocols/HTTPS/my_server.cpp:1:
.pio/libdeps/esp01_1m/esp32_https_server/src/ResourceNode.hpp:18:3: note: candidate: httpsserver::ResourceNode::ResourceNode(const string&, const string&, void (*)(httpsserver::HTTPRequest*, httpsserver::HTTPResponse*), const string&)
   ResourceNode(const std::string &path, const std::string &method, const HTTPSCallbackFunction * callback, const std::string &tag = "");
   ^
.pio/libdeps/esp01_1m/esp32_https_server/src/ResourceNode.hpp:18:3: note:   no known conversion for argument 3 from 'void (HttpsHandler::*)(httpsserver::HTTPRequest*, httpsserver::HTTPResponse*)' to 'void (*)(httpsserver::HTTPRequest*, httpsserver::HTTPResponse*)'
.pio/libdeps/esp01_1m/esp32_https_server/src/ResourceNode.hpp:16:7: note: candidate: httpsserver::ResourceNode::ResourceNode(const httpsserver::ResourceNode&)
 class ResourceNode : public HTTPNode {
       ^
.pio/libdeps/esp01_1m/esp32_https_server/src/ResourceNode.hpp:16:7: note:   candidate expects 1 argument, 3 provided
*** [.pio/build/esp01_1m/src/system/communication/protocols/HTTPS/my_server.cpp.o] Error 1

Is it possible to do what I am proposing? how?
I'm a beginner in CPP

thanks in advance

ESP32-D0WDQ6 (revision 1)

  • Flash Size: 4MB

Tools

  • IDE and Version: vscode 1.51.1
  • OS: Ubuntu 18.04.4 LTS
@fhessel
Copy link
Owner

fhessel commented Dec 7, 2020

That won't work with the current release version, but #91 enables it when merged.

However, you cannot use your class method without an instance. So at some point, you need to create an instance of your HttpsHandler.

If that instance is called myHandler, the code would look like this:

// At the top of your sketch:
#include <HTTPSCallbackFunction.hpp>

// In your setup code:
HTTPSCallbackFunction handler =
          std::bind(&HttpsHandler::root, &myHandler, std::placeholders::_1, std::placeholders::_2);
server.registerNode(new ResourceNode("/", "GET", handler));

A bit simplified, using bind creates a pointer to that root method that knows on which instance it should be executed. The placeholders allow to pass-through the req and res parameters.

#90 has more details on this.

@marfanjr
Copy link
Author

marfanjr commented Dec 7, 2020

Thanks for the quick response!
Do you have any predictions of when the PR will be merged?
I tested the PR branch and it worked perfectly!

@fhessel
Copy link
Owner

fhessel commented Dec 7, 2020

Thanks for testing and giving feedback! I'm currently working on building a reliable, automated, and hardware-based CI pipeline for this repository, since I want to be sure that after merging a PR the examples still work (not only that they are able to build) and to be able to test all functionality in isolation. Doing that manually for each PR takes me some hours each time I'm merging something, which makes it hard to merge even little changes.

For that reason I decided to prioritize working on the CI first instead of spending my (currently quite limited) spare time on manual testing – that's also the reason why most issues are stale at the moment. I hope to get everything running around Christmas, and then merging PRs and working on issues should be easier and be doable with more confidence in the codebase.

If I don't stumble upon any issues with the way the PR is implemented, it will stay as it is. So you could in theory start working on the PR branch, since the only code changes to 1.0.0 are the ones required for implementing the callbacks, all other commits are just documentation, and when 1.1.0 is out, you could switch back to using normal semver.

@marfanjr
Copy link
Author

marfanjr commented Dec 8, 2020

Excellent decision! I will continue using the pr branch and awaiting the merge.

Thank you very much for your attention! I hope to be able to contribute to the community as I progress in my studies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants