diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 862efefa..07c05c16 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -116,6 +116,22 @@ "problemMatcher": [ "$gcc" ] + }, + { + "label": "X86_64 - make clean - uhttpd-rest-api", + "options": { + "cwd": "${workspaceRoot}/_builds/x86_64_domo-debug/buildroot/build/uhttpd-rest-api", + }, + "type": "shell", + "command": "make clean", + "group": "build", + "presentation": { + "echo": true, + "reveal": "always" + }, + "problemMatcher": [ + "$gcc" + ] } ] } diff --git a/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.cpp b/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.cpp index a14dc190..a5c9250e 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.cpp +++ b/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.cpp @@ -104,3 +104,14 @@ bool WebController::find(uint8_t a_method, const std::string &an_url) { return true; } + +/*! ---------------------------------------------------------------------------- + * @fn find + * + * @brief return true if the controller match with the url. + */ +std::string WebController::get_parameter(const std::string &an_url) +{ + std::string the_parameter; + return the_parameter; +} diff --git a/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.h b/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.h index d951a2f0..e6d0e0c7 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.h +++ b/src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.h @@ -45,6 +45,7 @@ class WebController virtual ~WebController(void); virtual bool find(uint8_t a_method, const std::string &an_url); + virtual std::string get_parameter(const std::string &an_url); void set_name(const std::string &a_name); const std::string &get_name(void); diff --git a/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.cpp b/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.cpp index 79b3f6d9..98e32526 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.cpp +++ b/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.cpp @@ -96,7 +96,7 @@ void RestConnection::invoke(struct ubus_context *a_ctx) m_ctx = a_ctx; - // printf("RestConnection::invoke(object: %s)....\n", m_controller->get_path().c_str()); + printf("RestConnection::invoke(object: %s)....\n", m_controller->get_path().c_str()); if (!ubus_lookup_id(a_ctx, m_controller->get_ubus().get_path().c_str(), &the_id)) { json_object *the_parameter_doc; @@ -107,6 +107,8 @@ void RestConnection::invoke(struct ubus_context *a_ctx) the_parameter_doc = parse_form_encoded_data(); // printf("RestConnection::invoke launch async call (%d)....\n", the_id); + printf("RestConnection::invoke - param:(%s)....\n", json_object_to_json_string(the_parameter_doc)); + the_cmd.exec_async(a_ctx, the_id, m_controller->get_ubus().get_method().c_str(), json_object_to_json_string(the_parameter_doc), this); diff --git a/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.cpp b/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.cpp index 2b8979df..95fa2f88 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.cpp +++ b/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.cpp @@ -24,6 +24,8 @@ #include +#include + #include #include "rest/rest-connection.h" @@ -44,8 +46,9 @@ * * @brief constructor of the rest controller object. */ -RestController::RestController(void) +RestController::RestController(void) : m_parameter_position(std::string::npos) { + printf("constructor empty.\n"); } /*! ---------------------------------------------------------------------------- @@ -128,6 +131,8 @@ bool RestController::from_json(struct json_object *a_node) } } + manage_endpoint(); + return true; } @@ -141,26 +146,73 @@ bool RestController::find(uint8_t a_method, const std::string &an_url) std::vector::iterator the_it; std::size_t the_pos; - printf("find : url: %s, endpoint:%s \n", an_url.c_str(), m_endpoint.c_str()); - + printf("find : url: %s, endpoint:%s method: %d ubus:%s\n", an_url.c_str(), m_endpoint.c_str(), a_method, get_ubus().get_method().c_str()); if ((m_endpoint == an_url) && (m_method == a_method)) { return true; } - the_pos = m_endpoint.find_first_of(":"); - if (the_pos == std::string::npos) + // Check if we have a parameter. + if (m_parameter_position == std::string::npos) { return false; } - printf("ya un param.\n"); - std::string the_endpoint = m_endpoint.substr(the_pos); + std::string the_endpoint = m_endpoint.substr(0, m_parameter_position); + + // Remove the last char if it's a / + the_pos = the_endpoint.find_last_of("/"); + if(the_pos != std::string::npos) + { + the_endpoint.erase(the_pos); + } + printf("endpoint: %s\n", the_endpoint.c_str()); - - return false; + + the_pos = an_url.find(the_endpoint); + if (the_pos == std::string::npos) + { + return false; + } + + if (m_method != a_method) + { + printf ("pas la bonne methode.(%d) != (%d)\n", m_method, a_method); + return false; + } + + printf("!!!!!! c'est bon. c'est le meme.\n"); + return true; } +/*! ---------------------------------------------------------------------------- + * @fn find + * + * @brief return true if the controller match with the url. + */ +std::string RestController::get_parameter(const std::string &an_uri) +{ + std::size_t the_pos; + std::string the_tmp; + std::string the_parameter; + + if (m_parameter_position != std::string::npos) + { + the_tmp = an_uri.substr(m_parameter_position); + printf("uri: %s, tmp: %s pos: %d\n", an_uri.c_str(), the_tmp.c_str(), (int)m_parameter_position); + } + + the_pos = the_tmp.find_first_of("/"); + if (the_pos != std::string::npos) + { + the_tmp = the_tmp.substr(0, the_pos); + the_parameter = fmt::format("{}={}", m_parameter_name, the_tmp); + } + + return the_parameter; +} + + /*! ---------------------------------------------------------------------------- * @fn get_ubus * @@ -176,12 +228,21 @@ const Ubus &RestController::get_ubus(void) const * * @brief return the endpoint for this controller. */ - const std::string &RestController::get_endpoint(void) const { return m_endpoint; } +/*! ---------------------------------------------------------------------------- + * @fn get_method + * + * @brief return the method for this controller. + */ +const uint8_t RestController::get_method(void) const +{ + return m_method; +} + /*! ---------------------------------------------------------------------------- * @fn is_raw_response * @@ -192,6 +253,58 @@ bool RestController::is_raw_response(void) return mf_raw_response; } + +/*! ---------------------------------------------------------------------------- + * @fn manage_endpoint + * + * @brief manage the endpoint to check if we have a parameter on it. + */ +void RestController::manage_endpoint(void) +{ + std::size_t the_pos; + + // Check if we have a parameter. + the_pos = m_endpoint.find_first_of(":"); + if (the_pos == std::string::npos) + { + return; + } + + m_parameter_name = m_endpoint.substr(the_pos + 1); + + m_parameter_position = the_pos; + the_pos = m_parameter_name.find_first_of("/"); + if (the_pos != std::string::npos) + { + m_controller = m_parameter_name.substr(the_pos + 1); + m_parameter_name = m_parameter_name.substr(0, the_pos); + } + printf ("endpoint: %s pos: %d ubus: %s\n", m_endpoint.c_str(), (int)m_parameter_position, get_ubus().get_method().c_str()); +} + + +#if 0 + std::string + + // Remove the last char if it's a / + the_pos = the_endpoint.find_last_of("/"); + if(the_pos != std::string::npos) + { + the_endpoint.erase(the_pos); + } + + printf("endpoint: %s\n", the_endpoint.c_str()); + + the_pos = an_url.find(the_endpoint); + if (the_pos == std::string::npos) + { + return false; + } + + printf("c'est bon. c'est le meme.\n"); + return true; +#endif + #if 0 /*! ---------------------------------------------------------------------------- * @fn get_method_get diff --git a/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.h b/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.h index 16992ff1..f5b3f2e7 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.h +++ b/src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.h @@ -56,8 +56,11 @@ class RestController : public WebController bool from_json(struct json_object *a_node); bool find(uint8_t a_method, const std::string &an_url); + std::string get_parameter(const std::string &an_url); const Ubus &get_ubus(void) const; + + const uint8_t get_method(void) const; const std::string &get_endpoint(void) const; bool is_raw_response(void); @@ -82,6 +85,13 @@ class RestController : public WebController std::string m_method_put; uint16_t m_timeout; */ + +private: + void manage_endpoint(void); + std::string m_parameter_name; + std::size_t m_parameter_position; + std::string m_controller; + }; #endif /* _REST_CONTROLLER_H */ diff --git a/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.cpp b/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.cpp index 27ca6f60..91cbbaf4 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.cpp +++ b/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.cpp @@ -332,7 +332,8 @@ void UhttpServer::handle_request(struct client *a_cl, const std::string &an_url, return; } -#warning TODO check if controller is available for this method. + the_parameters = the_controller->get_parameter(the_url); + printf ("the parameter: %s\n", the_parameters.c_str()); // We found the controller. // printf("method: %d\n", a_cl->request.method); struct dispatch *d = &a_cl->dispatch; @@ -480,8 +481,10 @@ int UhttpServer::add_controller_from_json(struct json_object *a_root_node) if (the_rest_controller->from_json(the_ctrl_node)) { + ControllerKey the_key; //new RestController(the_model_name, the_get_method, the_set_method, kDefaultTimeout, the_raw_response) - add_controller(the_rest_controller->get_endpoint(), the_rest_controller); + the_key = std::make_pair(the_rest_controller->get_method(), the_rest_controller->get_endpoint()); + add_controller(the_key, the_rest_controller); } } } @@ -497,8 +500,10 @@ int UhttpServer::add_controller_from_json(struct json_object *a_root_node) { EtagRestController *the_etag_rest_controller; the_etag_rest_controller = new EtagRestController(the_model_name, the_event_name, the_etag_key, the_get_method, the_set_method, kDefaultTimeout, the_raw_response); - - add_controller(the_path, the_etag_rest_controller); + ControllerKey the_key; + //new RestController(the_model_name, the_get_method, the_set_method, kDefaultTimeout, the_raw_response) + the_key = std::make_pair(0, the_model_name); + add_controller(the_key, the_etag_rest_controller); } } } @@ -514,7 +519,10 @@ int UhttpServer::add_controller_from_json(struct json_object *a_root_node) { NotificationController *the_notification_controller; the_notification_controller = new NotificationController(the_event_name); - add_controller(the_path, the_notification_controller); + ControllerKey the_key; + //new RestController(the_model_name, the_get_method, the_set_method, kDefaultTimeout, the_raw_response) + the_key = std::make_pair(0, the_event_name); + add_controller(the_key, the_notification_controller); } } } @@ -650,7 +658,7 @@ struct json_object *UhttpServer::load(const std::string &a_file) * * @brief add a rest controller. */ -int UhttpServer::add_controller(const std::string &an_uri, WebController *a_controller) +int UhttpServer::add_controller(ControllerKey a_key, WebController *a_controller) { std::string the_path; std::size_t the_pos; @@ -658,8 +666,9 @@ int UhttpServer::add_controller(const std::string &an_uri, WebController *a_cont if (a_controller == NULL) return -1; - a_controller->set_name(an_uri); - m_controllers[an_uri] = std::unique_ptr(a_controller); +// a_controller->set_name(an_uri); + + m_controllers[a_key] = std::unique_ptr(a_controller); //m_controller_array[an_uri] = a_controller; diff --git a/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.h b/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.h index 18e8e653..aa486c97 100644 --- a/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.h +++ b/src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.h @@ -29,6 +29,7 @@ #include #include #include +#include /*--------------------------------- Define ----------------------------------*/ @@ -43,10 +44,23 @@ class WebConnection; /*--------------------------------- CLASS ----------------------------------*/ +struct pair_hash { + template + std::size_t operator () (const std::pair &p) const { + auto h1 = std::hash{}(p.first); + auto h2 = std::hash{}(p.second); + + // Mainly for demonstration purposes, i.e. works but is overly simple + // In the real world, use sth. like boost.hash_combine + return h1 ^ h2; + } +}; + class UhttpServer { public: - typedef std::unordered_map> ControllerContainer; + typedef std::pair ControllerKey; + typedef std::unordered_map, pair_hash> ControllerContainer; typedef ControllerContainer::iterator ControllerIterator; typedef std::unordered_map ConnectionContainer; typedef ConnectionContainer::iterator ConnectionIterator; @@ -75,7 +89,7 @@ class UhttpServer std::string &an_event_name, std::string &an_etag_key, std::string &a_get_method, std::string &a_set_method, bool &a_raw_response); struct json_object *load(const std::string &a_file); - int add_controller(const std::string &an_uri, WebController *a_controller); + int add_controller(ControllerKey a_key, WebController *a_controller); WebController *get_controller(uint8_t a_method, const std::string &an_url); void send_error(struct client *a_cl, int a_code, const char *a_summary, const std::string &a_msg);