wip to new rest method

This commit is contained in:
2018-05-21 22:28:10 +02:00
parent 49972f892b
commit 81442524a3
8 changed files with 197 additions and 21 deletions

16
.vscode/tasks.json vendored
View File

@@ -116,6 +116,22 @@
"problemMatcher": [ "problemMatcher": [
"$gcc" "$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"
]
} }
] ]
} }

View File

@@ -104,3 +104,14 @@ bool WebController::find(uint8_t a_method, const std::string &an_url)
{ {
return true; 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;
}

View File

@@ -45,6 +45,7 @@ class WebController
virtual ~WebController(void); virtual ~WebController(void);
virtual bool find(uint8_t a_method, const std::string &an_url); 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); void set_name(const std::string &a_name);
const std::string &get_name(void); const std::string &get_name(void);

View File

@@ -96,7 +96,7 @@ void RestConnection::invoke(struct ubus_context *a_ctx)
m_ctx = 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)) if (!ubus_lookup_id(a_ctx, m_controller->get_ubus().get_path().c_str(), &the_id))
{ {
json_object *the_parameter_doc; json_object *the_parameter_doc;
@@ -107,6 +107,8 @@ void RestConnection::invoke(struct ubus_context *a_ctx)
the_parameter_doc = parse_form_encoded_data(); the_parameter_doc = parse_form_encoded_data();
// printf("RestConnection::invoke launch async call (%d)....\n", the_id); // 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(), 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); json_object_to_json_string(the_parameter_doc), this);

View File

@@ -24,6 +24,8 @@
#include <cstddef> #include <cstddef>
#include <fmt/format.h>
#include <json-c/json.h> #include <json-c/json.h>
#include "rest/rest-connection.h" #include "rest/rest-connection.h"
@@ -44,8 +46,9 @@
* *
* @brief constructor of the rest controller object. * @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; return true;
} }
@@ -141,26 +146,73 @@ bool RestController::find(uint8_t a_method, const std::string &an_url)
std::vector<std::string>::iterator the_it; std::vector<std::string>::iterator the_it;
std::size_t the_pos; 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)) if ((m_endpoint == an_url) && (m_method == a_method))
{ {
return true; return true;
} }
the_pos = m_endpoint.find_first_of(":"); // Check if we have a parameter.
if (the_pos == std::string::npos) if (m_parameter_position == std::string::npos)
{ {
return false; return false;
} }
printf("ya un param.\n"); std::string the_endpoint = m_endpoint.substr(0, m_parameter_position);
std::string the_endpoint = m_endpoint.substr(the_pos);
// 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()); 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 * @fn get_ubus
* *
@@ -176,12 +228,21 @@ const Ubus &RestController::get_ubus(void) const
* *
* @brief return the endpoint for this controller. * @brief return the endpoint for this controller.
*/ */
const std::string &RestController::get_endpoint(void) const const std::string &RestController::get_endpoint(void) const
{ {
return m_endpoint; 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 * @fn is_raw_response
* *
@@ -192,6 +253,58 @@ bool RestController::is_raw_response(void)
return mf_raw_response; 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 #if 0
/*! ---------------------------------------------------------------------------- /*! ----------------------------------------------------------------------------
* @fn get_method_get * @fn get_method_get

View File

@@ -56,8 +56,11 @@ class RestController : public WebController
bool from_json(struct json_object *a_node); bool from_json(struct json_object *a_node);
bool find(uint8_t a_method, const std::string &an_url); 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 Ubus &get_ubus(void) const;
const uint8_t get_method(void) const;
const std::string &get_endpoint(void) const; const std::string &get_endpoint(void) const;
bool is_raw_response(void); bool is_raw_response(void);
@@ -82,6 +85,13 @@ class RestController : public WebController
std::string m_method_put; std::string m_method_put;
uint16_t m_timeout; 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 */ #endif /* _REST_CONTROLLER_H */

View File

@@ -332,7 +332,8 @@ void UhttpServer::handle_request(struct client *a_cl, const std::string &an_url,
return; 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. // We found the controller.
// printf("method: %d\n", a_cl->request.method); // printf("method: %d\n", a_cl->request.method);
struct dispatch *d = &a_cl->dispatch; 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)) 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) //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; 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); 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);
ControllerKey the_key;
add_controller(the_path, the_etag_rest_controller); //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; NotificationController *the_notification_controller;
the_notification_controller = new NotificationController(the_event_name); 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. * @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::string the_path;
std::size_t the_pos; 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) if (a_controller == NULL)
return -1; return -1;
a_controller->set_name(an_uri); // a_controller->set_name(an_uri);
m_controllers[an_uri] = std::unique_ptr<WebController>(a_controller);
m_controllers[a_key] = std::unique_ptr<WebController>(a_controller);
//m_controller_array[an_uri] = a_controller; //m_controller_array[an_uri] = a_controller;

View File

@@ -29,6 +29,7 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
#include <utility>
/*--------------------------------- Define ----------------------------------*/ /*--------------------------------- Define ----------------------------------*/
@@ -43,10 +44,23 @@ class WebConnection;
/*--------------------------------- CLASS ----------------------------------*/ /*--------------------------------- CLASS ----------------------------------*/
struct pair_hash {
template <class T1, class T2>
std::size_t operator () (const std::pair<T1,T2> &p) const {
auto h1 = std::hash<T1>{}(p.first);
auto h2 = std::hash<T2>{}(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 class UhttpServer
{ {
public: public:
typedef std::unordered_map<std::string, std::unique_ptr<WebController>> ControllerContainer; typedef std::pair <uint8_t, std::string> ControllerKey;
typedef std::unordered_map<ControllerKey, std::unique_ptr<WebController>, pair_hash> ControllerContainer;
typedef ControllerContainer::iterator ControllerIterator; typedef ControllerContainer::iterator ControllerIterator;
typedef std::unordered_map<int, WebConnection *> ConnectionContainer; typedef std::unordered_map<int, WebConnection *> ConnectionContainer;
typedef ConnectionContainer::iterator ConnectionIterator; typedef ConnectionContainer::iterator ConnectionIterator;
@@ -75,7 +89,7 @@ class UhttpServer
std::string &an_event_name, std::string &an_etag_key, std::string &an_event_name, std::string &an_etag_key,
std::string &a_get_method, std::string &a_set_method, bool &a_raw_response); std::string &a_get_method, std::string &a_set_method, bool &a_raw_response);
struct json_object *load(const std::string &a_file); 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); 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); void send_error(struct client *a_cl, int a_code, const char *a_summary, const std::string &a_msg);