From 1b922f7319f821fe3daf302a8c68131aaa94f586 Mon Sep 17 00:00:00 2001 From: neodarz Date: Fri, 6 Sep 2019 18:04:40 +0200 Subject: Change code to use Restbed --- api/umosapi.cpp | 480 +++++++++++++++++++++++++++++++++++++++++++------------- api/umosapi.h | 105 +++++++++++-- 2 files changed, 462 insertions(+), 123 deletions(-) (limited to 'api') diff --git a/api/umosapi.cpp b/api/umosapi.cpp index 83965a3..af58b37 100644 --- a/api/umosapi.cpp +++ b/api/umosapi.cpp @@ -17,6 +17,12 @@ #include "../db/mongo_access.h" #include "../db/uobject.h" +#include +#include +#include +#include +#include + mongo_access mongo; @@ -30,133 +36,395 @@ using bsoncxx::builder::stream::open_document; using json = nlohmann::json; using namespace std; -using namespace Pistache; +using namespace restbed; -namespace Generic { - void handleReady(const Rest::Request&, Http::ResponseWriter response) { - response.send(Http::Code::Ok, "1"); - } -} +UmosapiService::UmosapiService() {} -UmosapiService::UmosapiService(Address addr) - : httpEndpoint(std::make_shared(addr)) - , desc("Unity Mongo Save API", "0.1") -{ } +void UmosapiService::init() { -void UmosapiService::init(size_t thr = 2) { auto uri = mongocxx::uri{config["mongoURI"]}; mongo.configure(std::move(uri)); - auto opts = Http::Endpoint::options() - .threads(thr); - httpEndpoint->init(opts); - createDescription(); -} - -void UmosapiService::start(std::string swaggerui) { - router.initFromDescription(desc); - - Rest::Swagger swagger(desc); - swagger - .uiPath("/doc") - .uiDirectory(swaggerui) - .apiPath("/api") - .serializer(&Rest::Serializer::rapidJson) - .install(router); - - httpEndpoint->setHandler(router.handler()); - httpEndpoint->serve(); -} - -void UmosapiService::createDescription() { - desc - .info() - .license("Apache", "https://neodarz.net"); - - auto backendErrorResponse = - desc.response(Http::Code::Internal_Server_Error, "Backend is dead, it's the end of the world"); - - desc - .schemes(Rest::Scheme::Http) - .basePath("/v1") - .produces(MIME(Application, Json)) - .consumes(MIME(Application, Json)); - - desc - .route(desc.get("/ready")) - .bind(&Generic::handleReady) - .response(Http::Code::Ok, "Api started") - .response(backendErrorResponse); - - auto versionPath = desc.path("/v1"); - - versionPath - .route(desc.get("/:mcollection")) - .bind(&UmosapiService::UmosapiService::retrieveAll, this) - .produces(MIME(Application, Json)) - .parameter("mcollection", "Name of the collection where the uobjects are located") - .response(Http::Code::Ok, "List of uobjects") - .response(backendErrorResponse); - - versionPath - .route(desc.post("/:mcollection")) - .bind(&UmosapiService::UmosapiService::addUObject, this) - .produces(MIME(Application, Json)) - .parameter("mcollection", "Name of the collection where the uobjects are located") - .response(Http::Code::Ok, "Uobject created") - .response(backendErrorResponse); - - versionPath - .route(desc.del("/:mcollection/:oid")) - .bind(&UmosapiService::UmosapiService::deleteUObject, this) - .produces(MIME(Application, Json)) - .parameter("mcollection", "Name of the collection where the uobjects are located") - .parameter("oid", "MongoDB oid of the uobject") - .response(Http::Code::Ok, "Uobject deleted") - .response(backendErrorResponse); - - versionPath - .route(desc.get("/:mcollection/:key/:value")) - .bind(&UmosapiService::UmosapiService::searchUObjectByKeyValue, this) - .produces(MIME(Application, Json)) - .parameter("mcollection", "Name of the collection where the uobjects are located") - .parameter("key", "Key of uobject to search, ex.: kil or total.kill") - .parameter("value", "Value of uobject to search, ex.: 12") - .response(Http::Code::Ok, "Uobject found") - .response(backendErrorResponse); -} - -void UmosapiService::retrieveAll(const Rest::Request& request, Http::ResponseWriter response) { - auto jsonObjects = json_object_new_array(); - auto json_string = uobject::retrieveAll(request.param(":mcollection").as(), jsonObjects); - json_object_put(jsonObjects); + createResource(); + ofstream swagger_json; + swagger_json.open(config["swaggerui"] + "/swagger.json"); + swagger_json << _swagger.dump(); + swagger_json.close(); +} - response.send(Http::Code::Ok, json_string, MIME(Application, Json)); +void UmosapiService::start(int port, int thr) { + auto settings = make_shared< Settings >(); + settings->set_port( port ); + settings->set_worker_limit( thr ); + settings->set_default_header("Connection", "close"); + _service.start(settings); } -void UmosapiService::addUObject(const Rest::Request& request, Http::ResponseWriter response) { - auto jsonObject = json_object_new_object(); +void service_error_handler( const int, const exception& e, const shared_ptr< Session > session ) +{ + std::string message = "Backend Service is dead: "; + message += e.what(); + if ( session->is_open( ) ) + session->close( 500, message, { { "Content-Length", ::to_string(message.length()) } } ); + fprintf( stderr, "ERROR: %s.\n", message.c_str() ); +} - auto json_string = uobject::add(request.param(":mcollection").as(), jsonObject, request.body().c_str()); +void resource_error_handler( const int, const exception& e, const shared_ptr< Session > session ) +{ + std::string message = "Backend Resource is dead: "; + message += e.what(); + if ( session->is_open( ) ) + session->close( 500, message, { { "Content-Length", ::to_string(message.length()) } } ); + fprintf( stderr, "ERROR: %s.\n", message.c_str() ); +} - response.send(Http::Code::Ok, json_string, MIME(Application, Json)); - json_object_put(jsonObject); +void faulty_method_handler( const shared_ptr< Session > ) +{ + throw SERVICE_UNAVAILABLE; +} + +void is_ready(const shared_ptr session) +{ + session->close( OK, "1", { { "Content-Length", "1"}}); +} + +/* + * Add new route in service + * service: the service pointer + * route: path of the route + * http_word: word http who defin REST request + * callback: function to call when the route is requested + * error_callback: error to show if everything is broken + * tags: array of tags + */ +void UmosapiService::desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback, tag tags[]) { + auto resource = make_shared< Resource > (); + resource->set_path(route); + resource->set_method_handler(http_word, callback); + resource->set_error_handler( error_callback ); + + _service.publish(resource); +} + +void UmosapiService::description(std::string description) { + _swagger["info"]["description"] = description; +} + +void UmosapiService::title(std::string title) { + _swagger["info"]["title"] = title; +} + +void UmosapiService::version(std::string version) { + _swagger["info"]["version"] = version; +} + +void UmosapiService::basePath(std::string basePath) { + _swagger["swagger"] = "2.0"; + _swagger["basePath"] = basePath; +} + +void UmosapiService::host(std::string host) { + _swagger["host"] = host; +} + +void UmosapiService::atag(std::string name, std::string description) { + struct tag the_tag; + the_tag.name = name; + the_tag.description = description; + + _tags.push_back(the_tag); + _swagger["tags"].push_back({ {"name",the_tag.name},{"description", the_tag.description} }); + +} + +void UmosapiService::scheme(std::string scheme) { + _swagger["schemes"].push_back(scheme); +} + +void UmosapiService::set_path(std::string route) { + _resource = make_shared< Resource > (); + _resource->set_path(route); + std::regex parameter(":.*?}"); + std::regex base_path("^/v2"); + auto tmp_route = std::regex_replace (route,parameter,"}"); + auto final_route = std::regex_replace (tmp_route,base_path,""); + _path = Path{final_route}; + _swagger["paths"][final_route] = {}; +} + +void UmosapiService::set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback) { + _resource->set_method_handler(http_word, callback); + std::locale loc; + for (auto& c : http_word) { + c = tolower(c); + } + _path.words.push_back(HttpWord{http_word}); + _swagger["paths"][_path.name][http_word]["description"] = ""; + _swagger["paths"][_path.name][http_word]["operationId"] = ""; + _swagger["paths"][_path.name][http_word]["summary"] = ""; +} + +void UmosapiService::set_error_handler(const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback) { + _resource->set_error_handler( error_callback ); +} + +void UmosapiService::publish() { + for (auto& http_word: _path.words) { + auto responses = _swagger["paths"][_path.name][http_word.name]["responses"]; + if (responses.find("200") == responses.end()) { + _swagger["paths"][_path.name][http_word.name]["responses"]["200"]["description"] = "All is fine."; + } + } + _service.publish(_resource); +} + +void UmosapiService::definition(std::string name, std::string type) { + _definition = Definition{name, type}; + _definitions.defs.push_back(_definition); + _swagger["definitions"][name]["type"] = type; +} + +void UmosapiService::propertie(std::string name, std::string format, std::string type, std::string required) { + _definition.props.push_back(Propertie{name, format, type, required}); + _swagger["definitions"][_definition.name]["properties"][name]["format"] = format; + _swagger["definitions"][_definition.name]["properties"][name]["type"] = type; + if (required == "true") { + _swagger["definitions"][_definition.name]["required"].push_back(name); + } +} + +void UmosapiService::consume(std::string consume) { + _swagger["paths"][_path.name][_path.words.back().name]["consumes"].push_back(consume); +} + +void UmosapiService::produce(std::string produce) { + _swagger["paths"][_path.name][_path.words.back().name]["produces"].push_back(produce); +} + +void UmosapiService::parameter(std::string name, std::string description, std::string schema = "") { + json parameter; + parameter["name"] = name; + parameter["description"] = description; + parameter["required"] = true; + if (schema == "") { + parameter["type"] = "string"; + parameter["in"] = "path"; + } else { + parameter["in"] = "body"; + for (auto& def: _definitions.defs) { + if (def.name == schema ) { + std::string schema_path = "#/definitions/"; + parameter["schema"]["$ref"] = schema_path.append(schema); + } + } + } + _swagger["paths"][_path.name][_path.words.back().name]["parameters"].push_back(parameter); +} + +void UmosapiService::response(std::string http_code, std::string description, std::string definition) { + std::string schema = "#/definitions/"; + _swagger["paths"][_path.name][_path.words.back().name]["responses"][http_code]["description"] = description; + _swagger["paths"][_path.name][_path.words.back().name]["responses"][http_code]["schema"]["items"]["$ref"] = schema.append(definition); + _swagger["paths"][_path.name][_path.words.back().name]["responses"][http_code]["schema"]["type"] = "array"; +} + +void UmosapiService::swagger(std::string ui_path, std::string swagger_dir, std::string api_path) { + _resource = make_shared< Resource > (); + _resource->set_path(ui_path); + _resource->set_method_handler("GET", swaggerEndpoint); + _service.publish(_resource); + + _resource = make_shared< Resource > (); + _resource->set_path(ui_path + "/{filename: .*}"); + _resource->set_method_handler("GET", swaggerEndpointResources); + _service.publish(_resource); + + _resource = make_shared< Resource > (); + _resource->set_path(api_path); + _resource->set_method_handler("GET", swaggerEndpointApi); + _service.publish(_resource); +} + + +void UmosapiService::createResource() { + basePath("/v2"); + description("Umosapi rest api"); + version("0.1"); + title("UMOSAPI"); + host("127.0.0.1:"+config["port"]); + + swagger("/doc", config["swaggerui"], "/api"); + + atag("uobject", "Everything about your UObjec"); + + scheme("http"); + scheme("https"); + + definition("UObject", "object"); + propertie("id", "int64", "integer", "true"); + propertie("value", "string", "object", "true"); + + definition("UObjectSended", "object"); + + set_path("/v2/ready"); + set_method_handler("GET", is_ready); + produce("application/json"); + publish(); + + set_path("/v2/{mcollection: .*}"); + set_method_handler("GET", retrieveAll); + produce("application/json"); + parameter("mcollection", "Name of the collection where the uobject are located"); + set_error_handler(resource_error_handler); + set_method_handler("POST", addUObject); + consume("application/json"); + parameter("mcollection", "Name of the collection where the uobject are located"); + parameter("body", "UObject to add", "UObjectSended"); + set_error_handler(resource_error_handler); + publish(); + + set_path("/v2/{mcollection: .*}/{oid: .*}"); + set_method_handler("DELETE", deleteUObject); + produce("application/json"); + parameter("mcollection", "Name of the collection where the uobject are located" ); + parameter("oid", "MongoDB oid of the uobject"); + set_error_handler(resource_error_handler); + publish(); + + set_path("/v2/{mcollection: .*}/{key: .*}/{value: .*}"); + set_method_handler("GET", searchUObjectByKeyValue); + produce("application/json"); + parameter("mcollection", "Name of the collection where the uobject are located"); + parameter("key", "Key of uobject to search, ex: kill or total.kill"); + parameter("value", "Value of uobject to search, ex: 42"); + set_error_handler(resource_error_handler); + publish(); + + _service.set_error_handler( service_error_handler ); +} + +void UmosapiService::retrieveAll( const shared_ptr session ){ + auto jsonObjects = json_object_new_array(); + const auto& request = session->get_request( ); + auto json_string = uobject::retrieveAll(request->get_path_parameter( "mcollection" ), jsonObjects); + json_object_put(jsonObjects); + + session->close( OK, json_string, { + { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Type", "application/json" } + }); +} + +void UmosapiService::addUObject( const shared_ptr session ){ + const auto request = session->get_request(); + + size_t content_length = request->get_header( "Content-Length", 0 ); + + session->fetch( content_length, [ request ]( const shared_ptr< Session > session, const Bytes & body ) + { + auto jsonObject = json_object_new_object(); + char bodyData[body.size()+1]; + memset(bodyData, 0, sizeof(bodyData)); + snprintf(bodyData, sizeof(bodyData), "%.*s", ( int ) body.size( ), body.data()); + auto json_string = uobject::add(request->get_path_parameter("mcollection"), jsonObject, bodyData); + session->close( OK, json_string, { + { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Type", "application/json" } + }); + json_object_put(jsonObject); + } ); } -void UmosapiService::deleteUObject(const Rest::Request& request, Http::ResponseWriter response) { +void UmosapiService::deleteUObject( const shared_ptr session ){ auto jsonObject = json_object_new_object(); + const auto request = session->get_request(); - auto json_string = uobject::remove(request.param(":mcollection").as(), request.param(":oid").as(), jsonObject); + auto json_string = uobject::remove(request->get_path_parameter("mcollection"), request->get_path_parameter("oid"), jsonObject); - response.send(Http::Code::Ok, json_string, MIME(Application, Json)); + session->close( OK, json_string, { + { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Type", "application/json" } + }); json_object_put(jsonObject); } -void UmosapiService::searchUObjectByKeyValue(const Rest::Request& request, Http::ResponseWriter response) { +void UmosapiService::searchUObjectByKeyValue( const shared_ptr session ){ auto jsonObject = json_object_new_array(); + const auto request = session->get_request(); - auto json_string = uobject::searchKeyValue(request.param(":mcollection").as(), request.param(":key").as(), request.param(":value").as(), jsonObject); + auto json_string = uobject::searchKeyValue(request->get_path_parameter("mcollection"), request->get_path_parameter("key"), request->get_path_parameter("value"), jsonObject); - response.send(Http::Code::Ok, json_string, MIME(Application, Json)); + session->close( OK, json_string, { + { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Type", "application/json" } + }); json_object_put(jsonObject); } + +void UmosapiService::swaggerEndpoint( const shared_ptr session ){ + const auto request = session->get_request(); + + ifstream stream(config["swaggerui"] + "/index.html", ifstream::in ); + + if ( stream.is_open() ) { + const string body = string( istreambuf_iterator< char >(stream), istreambuf_iterator< char>()); + + const multimap< string, string> headers { + { "Content-Type", "text/html" }, + { "Content-Length", ::to_string( body.length() ) } + }; + session->close(OK, body, headers); + } else { + session->close( NOT_FOUND ); + } +} + +void UmosapiService::swaggerEndpointResources( const shared_ptr< Session > session ) +{ + const auto request = session->get_request( ); + const string filename = request->get_path_parameter( "filename" ); + + ifstream stream( config["swaggerui"] + "/" + filename, ifstream::in ); + + if ( stream.is_open( ) ) + { + const string body = string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); + + const multimap< string, string > headers + { + { "Content-Length", ::to_string( body.length( ) ) } + }; + + session->close( OK, body, headers ); + } + else + { + session->close( NOT_FOUND ); + } +} + +void UmosapiService::swaggerEndpointApi( const shared_ptr< Session > session ) +{ + const auto request = session->get_request( ); + const string filename = request->get_path_parameter( "filename" ); + const string path = request->get_path(); + + ifstream stream( config["swaggerui"] + "/swagger.json", ifstream::in ); + + if ( stream.is_open( ) ) + { + const string body = string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); + + const multimap< string, string > headers + { + { "Content-Type", "application/json" }, + { "Content-Length", ::to_string( body.length( ) ) } + }; + + session->close( OK, body, headers ); + } + else + { + session->close( NOT_FOUND ); + } +} diff --git a/api/umosapi.h b/api/umosapi.h index 20c6d7b..a1765d7 100644 --- a/api/umosapi.h +++ b/api/umosapi.h @@ -1,37 +1,108 @@ #ifndef UmosapiService_H_ #define UmosapiService_H_ -#include -#include -#include +//#include +//#include +//#include -#include +#include -using namespace Pistache; +//#include + +#include + +using namespace restbed; +using namespace std; + +using json = nlohmann::json; + +struct tag { + std::string name; + std::string description; +}; + +struct Propertie { + + std::string name; + std::string format; + std::string type; + std::string required; +}; + +struct Definition { + + std::string name; + std::string type; + std::vector props; +}; + +struct Definitions { + std::vector defs; +}; + +struct HttpWord { + std::string name; +}; + +struct Path { + std::string name; + std::vector words; +}; + +struct Paths { + std::vector paths; +}; class UmosapiService { public: - UmosapiService(Address addr); + UmosapiService(); virtual ~UmosapiService() {}; - void init(size_t thr); + void init(); - void start(std::string swaggerui); + void start(int, int); + Service _service; + json _swagger; + vector _tags; private: - void createDescription(); - - void retrieveAll(const Rest::Request& request, Http::ResponseWriter response); + void desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback, tag tags[]); + void createResource(); - void addUObject(const Rest::Request& request, Http::ResponseWriter response); + static void retrieveAll( const shared_ptr session ); + static void addUObject( const shared_ptr session ); + static void deleteUObject( const shared_ptr session ); + static void searchUObjectByKeyValue( const shared_ptr session ); + static void swaggerEndpoint( const shared_ptr session ); + static void swaggerEndpointResources( const shared_ptr session ); + static void swaggerEndpointApi( const shared_ptr session ); - void deleteUObject(const Rest::Request& request, Http::ResponseWriter response); + shared_ptr< Resource> _resource; + Definition _definition; + Definitions _definitions; + Path _path; + Paths _paths; + void set_path(); + void set_path(std::string route); + void set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback); + void set_error_handler(const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback); + void produce(std::string); + void consume(std::string); + void parameter(std::string, std::string, std::string); + void response(std::string err_code, std::string description, std::string schema); + void publish(); + void basePath(std::string basePath); + void description(std::string description); + void title(std::string title); + void version(std::string version); + void host(std::string host); + void atag(std::string name, std::string description); + void scheme(std::string scheme); - void searchUObjectByKeyValue(const Rest::Request& request, Http::ResponseWriter response); + void definition(std::string name, std::string type); + void propertie(std::string name, std::string format, std::string type, std::string required); + void swagger(std::string ui_path, std::string swagger_dir, std::string api_path); - std::shared_ptr httpEndpoint; - Rest::Description desc; - Rest::Router router; }; #endif -- cgit v1.2.1 From 5b66830ca806e00f415d6ee83b15e410130de371 Mon Sep 17 00:00:00 2001 From: neodarz Date: Mon, 9 Sep 2019 15:42:58 +0200 Subject: Add some adjustement to make server more stable --- api/umosapi.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'api') diff --git a/api/umosapi.cpp b/api/umosapi.cpp index af58b37..737df24 100644 --- a/api/umosapi.cpp +++ b/api/umosapi.cpp @@ -63,8 +63,11 @@ void service_error_handler( const int, const exception& e, const shared_ptr< Ses { std::string message = "Backend Service is dead: "; message += e.what(); - if ( session->is_open( ) ) - session->close( 500, message, { { "Content-Length", ::to_string(message.length()) } } ); + if ( session ) { + if ( session->is_open( ) ) { + session->close( 500, message, { { "Content-Length", ::to_string(message.length()) } } ); + } + } fprintf( stderr, "ERROR: %s.\n", message.c_str() ); } @@ -274,12 +277,12 @@ void UmosapiService::createResource() { set_method_handler("GET", retrieveAll); produce("application/json"); parameter("mcollection", "Name of the collection where the uobject are located"); - set_error_handler(resource_error_handler); + set_error_handler(&resource_error_handler); set_method_handler("POST", addUObject); consume("application/json"); parameter("mcollection", "Name of the collection where the uobject are located"); parameter("body", "UObject to add", "UObjectSended"); - set_error_handler(resource_error_handler); + set_error_handler(&resource_error_handler); publish(); set_path("/v2/{mcollection: .*}/{oid: .*}"); @@ -287,7 +290,7 @@ void UmosapiService::createResource() { produce("application/json"); parameter("mcollection", "Name of the collection where the uobject are located" ); parameter("oid", "MongoDB oid of the uobject"); - set_error_handler(resource_error_handler); + set_error_handler(&resource_error_handler); publish(); set_path("/v2/{mcollection: .*}/{key: .*}/{value: .*}"); @@ -296,7 +299,7 @@ void UmosapiService::createResource() { parameter("mcollection", "Name of the collection where the uobject are located"); parameter("key", "Key of uobject to search, ex: kill or total.kill"); parameter("value", "Value of uobject to search, ex: 42"); - set_error_handler(resource_error_handler); + set_error_handler(&resource_error_handler); publish(); _service.set_error_handler( service_error_handler ); @@ -306,12 +309,13 @@ void UmosapiService::retrieveAll( const shared_ptr session ){ auto jsonObjects = json_object_new_array(); const auto& request = session->get_request( ); auto json_string = uobject::retrieveAll(request->get_path_parameter( "mcollection" ), jsonObjects); - json_object_put(jsonObjects); session->close( OK, json_string, { { "Content-Length", ::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); + json_object_put(jsonObjects); + } void UmosapiService::addUObject( const shared_ptr session ){ -- cgit v1.2.1 From bc6aeaa834d666221171d302d4f101ce65608898 Mon Sep 17 00:00:00 2001 From: neodarz Date: Mon, 9 Sep 2019 17:17:44 +0200 Subject: Refactoring some code to be more readable --- api/umosapi.cpp | 365 +++++++++++++++++++++++++++----------------------------- api/umosapi.h | 9 +- 2 files changed, 185 insertions(+), 189 deletions(-) (limited to 'api') diff --git a/api/umosapi.cpp b/api/umosapi.cpp index 737df24..6b25124 100644 --- a/api/umosapi.cpp +++ b/api/umosapi.cpp @@ -23,69 +23,58 @@ #include #include -mongo_access mongo; - - -using bsoncxx::builder::stream::close_array; -using bsoncxx::builder::stream::close_document; -using bsoncxx::builder::stream::document; -using bsoncxx::builder::stream::finalize; -using bsoncxx::builder::stream::open_array; -using bsoncxx::builder::stream::open_document; +UmosapiService::mongo_access mongo; using json = nlohmann::json; -using namespace std; -using namespace restbed; - -UmosapiService::UmosapiService() {} +UmosapiService::Api::Api() {} -void UmosapiService::init() { +void UmosapiService::Api::init() { auto uri = mongocxx::uri{config["mongoURI"]}; mongo.configure(std::move(uri)); - createResource(); + UmosapiService::Api::createResource(); ofstream swagger_json; swagger_json.open(config["swaggerui"] + "/swagger.json"); - swagger_json << _swagger.dump(); + swagger_json << UmosapiService::Api::_swagger.dump(); swagger_json.close(); } -void UmosapiService::start(int port, int thr) { - auto settings = make_shared< Settings >(); +void UmosapiService::Api::start(int port, int thr) { + auto settings = make_shared< restbed::Settings >(); settings->set_port( port ); settings->set_worker_limit( thr ); settings->set_default_header("Connection", "close"); - _service.start(settings); + UmosapiService::Api::_service.start(settings); } -void service_error_handler( const int, const exception& e, const shared_ptr< Session > session ) +void service_error_handler( const int, const exception& e, const shared_ptr< restbed::Session > session ) { std::string message = "Backend Service is dead: "; message += e.what(); if ( session ) { if ( session->is_open( ) ) { - session->close( 500, message, { { "Content-Length", ::to_string(message.length()) } } ); + session->close( 500, message, { { "Content-Length", std::to_string(message.length()) } } ); } } fprintf( stderr, "ERROR: %s.\n", message.c_str() ); } -void resource_error_handler( const int, const exception& e, const shared_ptr< Session > session ) +void resource_error_handler( const int, const exception& e, const shared_ptr< restbed::Session > session ) { std::string message = "Backend Resource is dead: "; message += e.what(); if ( session->is_open( ) ) - session->close( 500, message, { { "Content-Length", ::to_string(message.length()) } } ); + session->close( 500, message, { { "Content-Length", std::to_string(message.length()) } } ); fprintf( stderr, "ERROR: %s.\n", message.c_str() ); } -void faulty_method_handler( const shared_ptr< Session > ) +void faulty_method_handler( const shared_ptr< restbed::Session > ) { throw SERVICE_UNAVAILABLE; } -void is_ready(const shared_ptr session) +void is_ready(const shared_ptr< restbed::Session > session) { session->close( OK, "1", { { "Content-Length", "1"}}); } @@ -99,111 +88,111 @@ void is_ready(const shared_ptr session) * error_callback: error to show if everything is broken * tags: array of tags */ -void UmosapiService::desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback, tag tags[]) { - auto resource = make_shared< Resource > (); +void UmosapiService::Api::desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< restbed::Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr< restbed::Session >) >& error_callback, tag tags[]) { + auto resource = make_shared< restbed::Resource > (); resource->set_path(route); resource->set_method_handler(http_word, callback); resource->set_error_handler( error_callback ); - _service.publish(resource); + UmosapiService::Api::_service.publish(resource); } -void UmosapiService::description(std::string description) { - _swagger["info"]["description"] = description; +void UmosapiService::Api::description(std::string description) { + UmosapiService::Api::_swagger["info"]["description"] = description; } -void UmosapiService::title(std::string title) { - _swagger["info"]["title"] = title; +void UmosapiService::Api::title(std::string title) { + UmosapiService::Api::_swagger["info"]["title"] = title; } -void UmosapiService::version(std::string version) { - _swagger["info"]["version"] = version; +void UmosapiService::Api::version(std::string version) { + UmosapiService::Api::_swagger["info"]["version"] = version; } -void UmosapiService::basePath(std::string basePath) { - _swagger["swagger"] = "2.0"; - _swagger["basePath"] = basePath; +void UmosapiService::Api::basePath(std::string basePath) { + UmosapiService::Api::_swagger["swagger"] = "2.0"; + UmosapiService::Api::_swagger["basePath"] = basePath; } -void UmosapiService::host(std::string host) { - _swagger["host"] = host; +void UmosapiService::Api::host(std::string host) { + UmosapiService::Api::_swagger["host"] = host; } -void UmosapiService::atag(std::string name, std::string description) { +void UmosapiService::Api::atag(std::string name, std::string description) { struct tag the_tag; the_tag.name = name; the_tag.description = description; - _tags.push_back(the_tag); - _swagger["tags"].push_back({ {"name",the_tag.name},{"description", the_tag.description} }); + UmosapiService::Api::_tags.push_back(the_tag); + UmosapiService::Api::_swagger["tags"].push_back({ {"name",the_tag.name},{"description", the_tag.description} }); } -void UmosapiService::scheme(std::string scheme) { - _swagger["schemes"].push_back(scheme); +void UmosapiService::Api::scheme(std::string scheme) { + UmosapiService::Api::_swagger["schemes"].push_back(scheme); } -void UmosapiService::set_path(std::string route) { - _resource = make_shared< Resource > (); - _resource->set_path(route); +void UmosapiService::Api::set_path(std::string route) { + UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource->set_path(route); std::regex parameter(":.*?}"); std::regex base_path("^/v2"); auto tmp_route = std::regex_replace (route,parameter,"}"); auto final_route = std::regex_replace (tmp_route,base_path,""); - _path = Path{final_route}; - _swagger["paths"][final_route] = {}; + UmosapiService::Api::_path = Path{final_route}; + UmosapiService::Api::_swagger["paths"][final_route] = {}; } -void UmosapiService::set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback) { - _resource->set_method_handler(http_word, callback); +void UmosapiService::Api::set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< restbed::Session > ) >& callback) { + UmosapiService::Api::_resource->set_method_handler(http_word, callback); std::locale loc; for (auto& c : http_word) { c = tolower(c); } - _path.words.push_back(HttpWord{http_word}); - _swagger["paths"][_path.name][http_word]["description"] = ""; - _swagger["paths"][_path.name][http_word]["operationId"] = ""; - _swagger["paths"][_path.name][http_word]["summary"] = ""; + UmosapiService::Api::_path.words.push_back(HttpWord{http_word}); + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word]["description"] = ""; + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word]["operationId"] = ""; + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word]["summary"] = ""; } -void UmosapiService::set_error_handler(const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback) { - _resource->set_error_handler( error_callback ); +void UmosapiService::Api::set_error_handler(const std::function< void(int, const std::exception&, std::shared_ptr< restbed::Session >) >& error_callback) { + UmosapiService::Api::_resource->set_error_handler( error_callback ); } -void UmosapiService::publish() { - for (auto& http_word: _path.words) { - auto responses = _swagger["paths"][_path.name][http_word.name]["responses"]; +void UmosapiService::Api::publish() { + for (auto& http_word: UmosapiService::Api::_path.words) { + auto responses = UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word.name]["responses"]; if (responses.find("200") == responses.end()) { - _swagger["paths"][_path.name][http_word.name]["responses"]["200"]["description"] = "All is fine."; + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word.name]["responses"]["200"]["description"] = "All is fine."; } } - _service.publish(_resource); + UmosapiService::Api::_service.publish(_resource); } -void UmosapiService::definition(std::string name, std::string type) { - _definition = Definition{name, type}; - _definitions.defs.push_back(_definition); - _swagger["definitions"][name]["type"] = type; +void UmosapiService::Api::definition(std::string name, std::string type) { + UmosapiService::Api::_definition = Definition{name, type}; + UmosapiService::Api::_definitions.defs.push_back(_definition); + UmosapiService::Api::_swagger["definitions"][name]["type"] = type; } -void UmosapiService::propertie(std::string name, std::string format, std::string type, std::string required) { - _definition.props.push_back(Propertie{name, format, type, required}); - _swagger["definitions"][_definition.name]["properties"][name]["format"] = format; - _swagger["definitions"][_definition.name]["properties"][name]["type"] = type; +void UmosapiService::Api::propertie(std::string name, std::string format, std::string type, std::string required) { + UmosapiService::Api::_definition.props.push_back(Propertie{name, format, type, required}); + UmosapiService::Api::_swagger["definitions"][UmosapiService::Api::_definition.name]["properties"][name]["format"] = format; + UmosapiService::Api::_swagger["definitions"][UmosapiService::Api::_definition.name]["properties"][name]["type"] = type; if (required == "true") { - _swagger["definitions"][_definition.name]["required"].push_back(name); + UmosapiService::Api::_swagger["definitions"][UmosapiService::Api::_definition.name]["required"].push_back(name); } } -void UmosapiService::consume(std::string consume) { - _swagger["paths"][_path.name][_path.words.back().name]["consumes"].push_back(consume); +void UmosapiService::Api::consume(std::string consume) { + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][UmosapiService::Api::_path.words.back().name]["consumes"].push_back(consume); } -void UmosapiService::produce(std::string produce) { - _swagger["paths"][_path.name][_path.words.back().name]["produces"].push_back(produce); +void UmosapiService::Api::produce(std::string produce) { + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][UmosapiService::Api::_path.words.back().name]["produces"].push_back(produce); } -void UmosapiService::parameter(std::string name, std::string description, std::string schema = "") { +void UmosapiService::Api::parameter(std::string name, std::string description, std::string schema = "") { json parameter; parameter["name"] = name; parameter["description"] = description; @@ -213,123 +202,125 @@ void UmosapiService::parameter(std::string name, std::string description, std::s parameter["in"] = "path"; } else { parameter["in"] = "body"; - for (auto& def: _definitions.defs) { + for (auto& def: UmosapiService::Api::_definitions.defs) { if (def.name == schema ) { std::string schema_path = "#/definitions/"; parameter["schema"]["$ref"] = schema_path.append(schema); } } } - _swagger["paths"][_path.name][_path.words.back().name]["parameters"].push_back(parameter); + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][UmosapiService::Api::_path.words.back().name]["parameters"].push_back(parameter); } -void UmosapiService::response(std::string http_code, std::string description, std::string definition) { +void UmosapiService::Api::response(std::string http_code, std::string description, std::string definition) { std::string schema = "#/definitions/"; - _swagger["paths"][_path.name][_path.words.back().name]["responses"][http_code]["description"] = description; - _swagger["paths"][_path.name][_path.words.back().name]["responses"][http_code]["schema"]["items"]["$ref"] = schema.append(definition); - _swagger["paths"][_path.name][_path.words.back().name]["responses"][http_code]["schema"]["type"] = "array"; -} - -void UmosapiService::swagger(std::string ui_path, std::string swagger_dir, std::string api_path) { - _resource = make_shared< Resource > (); - _resource->set_path(ui_path); - _resource->set_method_handler("GET", swaggerEndpoint); - _service.publish(_resource); - - _resource = make_shared< Resource > (); - _resource->set_path(ui_path + "/{filename: .*}"); - _resource->set_method_handler("GET", swaggerEndpointResources); - _service.publish(_resource); - - _resource = make_shared< Resource > (); - _resource->set_path(api_path); - _resource->set_method_handler("GET", swaggerEndpointApi); - _service.publish(_resource); -} - - -void UmosapiService::createResource() { - basePath("/v2"); - description("Umosapi rest api"); - version("0.1"); - title("UMOSAPI"); - host("127.0.0.1:"+config["port"]); - - swagger("/doc", config["swaggerui"], "/api"); - - atag("uobject", "Everything about your UObjec"); - - scheme("http"); - scheme("https"); - - definition("UObject", "object"); - propertie("id", "int64", "integer", "true"); - propertie("value", "string", "object", "true"); - - definition("UObjectSended", "object"); - - set_path("/v2/ready"); - set_method_handler("GET", is_ready); - produce("application/json"); - publish(); - - set_path("/v2/{mcollection: .*}"); - set_method_handler("GET", retrieveAll); - produce("application/json"); - parameter("mcollection", "Name of the collection where the uobject are located"); - set_error_handler(&resource_error_handler); - set_method_handler("POST", addUObject); - consume("application/json"); - parameter("mcollection", "Name of the collection where the uobject are located"); - parameter("body", "UObject to add", "UObjectSended"); - set_error_handler(&resource_error_handler); - publish(); - - set_path("/v2/{mcollection: .*}/{oid: .*}"); - set_method_handler("DELETE", deleteUObject); - produce("application/json"); - parameter("mcollection", "Name of the collection where the uobject are located" ); - parameter("oid", "MongoDB oid of the uobject"); - set_error_handler(&resource_error_handler); - publish(); - - set_path("/v2/{mcollection: .*}/{key: .*}/{value: .*}"); - set_method_handler("GET", searchUObjectByKeyValue); - produce("application/json"); - parameter("mcollection", "Name of the collection where the uobject are located"); - parameter("key", "Key of uobject to search, ex: kill or total.kill"); - parameter("value", "Value of uobject to search, ex: 42"); - set_error_handler(&resource_error_handler); - publish(); - - _service.set_error_handler( service_error_handler ); -} - -void UmosapiService::retrieveAll( const shared_ptr session ){ + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][UmosapiService::Api::_path.words.back().name]["responses"][http_code]["description"] = description; + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][UmosapiService::Api::_path.words.back().name]["responses"][http_code]["schema"]["items"]["$ref"] = schema.append(definition); + UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][UmosapiService::Api::_path.words.back().name]["responses"][http_code]["schema"]["type"] = "array"; +} + +void UmosapiService::Api::swagger(std::string ui_path, std::string swagger_dir, std::string api_path) { + UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource->set_path(ui_path); + UmosapiService::Api::_resource->set_method_handler("GET", swaggerEndpoint); + UmosapiService::Api::_service.publish(_resource); + + UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource->set_path(ui_path + "/{filename: .*}"); + UmosapiService::Api::_resource->set_method_handler("GET", swaggerEndpointResources); + UmosapiService::Api::_service.publish(_resource); + + UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource->set_path(api_path); + UmosapiService::Api::_resource->set_method_handler("GET", swaggerEndpointApi); + UmosapiService::Api::_service.publish(_resource); +} + + +void UmosapiService::Api::createResource() { + UmosapiService::Api::basePath("/v2"); + UmosapiService::Api::description("Umosapi rest api"); + UmosapiService::Api::version("0.1"); + UmosapiService::Api::title("UMOSAPI"); + UmosapiService::Api::host("127.0.0.1:"+config["port"]); + + UmosapiService::Api::swagger("/doc", config["swaggerui"], "/api"); + + UmosapiService::Api::atag("uobject", "Everything about your UObjec"); + + UmosapiService::Api::scheme("http"); + UmosapiService::Api::scheme("https"); + + UmosapiService::Api::definition("UObject", "object"); + UmosapiService::Api::propertie("id", "int64", "integer", "true"); + UmosapiService::Api::propertie("value", "string", "object", "true"); + + UmosapiService::Api::definition("UObjectSended", "object"); + + UmosapiService::Api::set_path("/v2/ready"); + UmosapiService::Api::set_method_handler("GET", is_ready); + UmosapiService::Api::produce("application/json"); + UmosapiService::Api::publish(); + + UmosapiService::Api::set_path("/v2/{mcollection: .*}"); + UmosapiService::Api::set_method_handler("GET", retrieveAll); + UmosapiService::Api::produce("application/json"); + UmosapiService::Api::parameter("mcollection", "Name of the collection where the uobject are located"); + UmosapiService::Api::set_error_handler(&resource_error_handler); + UmosapiService::Api::set_method_handler("POST", addUObject); + UmosapiService::Api::consume("application/json"); + UmosapiService::Api::parameter("mcollection", "Name of the collection where the uobject are located"); + UmosapiService::Api::parameter("body", "UObject to add", "UObjectSended"); + UmosapiService::Api::set_error_handler(&resource_error_handler); + UmosapiService::Api::publish(); + + UmosapiService::Api::set_path("/v2/{mcollection: .*}/{oid: .*}"); + UmosapiService::Api::set_method_handler("DELETE", deleteUObject); + UmosapiService::Api::produce("application/json"); + UmosapiService::Api::parameter("mcollection", "Name of the collection where the uobject are located" ); + UmosapiService::Api::parameter("oid", "MongoDB oid of the uobject"); + UmosapiService::Api::set_error_handler(&resource_error_handler); + UmosapiService::Api::publish(); + + UmosapiService::Api::set_path("/v2/{mcollection: .*}/{key: .*}/{value: .*}"); + UmosapiService::Api::set_method_handler("GET", searchUObjectByKeyValue); + UmosapiService::Api::produce("application/json"); + UmosapiService::Api::parameter("mcollection", "Name of the collection where the uobject are located"); + UmosapiService::Api::parameter("key", "Key of uobject to search, ex: kill or total.kill"); + UmosapiService::Api::parameter("value", "Value of uobject to search, ex: 42"); + UmosapiService::Api::set_error_handler(&resource_error_handler); + UmosapiService::Api::publish(); + + UmosapiService::Api::_service.set_error_handler( service_error_handler ); +} + +void UmosapiService::Api::retrieveAll( const shared_ptr< restbed::Session> session ){ + UmosapiService::uobject uobject; auto jsonObjects = json_object_new_array(); const auto& request = session->get_request( ); - auto json_string = uobject::retrieveAll(request->get_path_parameter( "mcollection" ), jsonObjects); + auto json_string = uobject.retrieveAll(request->get_path_parameter( "mcollection" ), jsonObjects); session->close( OK, json_string, { - { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); json_object_put(jsonObjects); } -void UmosapiService::addUObject( const shared_ptr session ){ +void UmosapiService::Api::addUObject( const shared_ptr< restbed::Session > session ){ const auto request = session->get_request(); size_t content_length = request->get_header( "Content-Length", 0 ); - session->fetch( content_length, [ request ]( const shared_ptr< Session > session, const Bytes & body ) + session->fetch( content_length, [ request ]( const shared_ptr< restbed::Session > session, const Bytes & body ) { + UmosapiService::uobject uobject; auto jsonObject = json_object_new_object(); char bodyData[body.size()+1]; memset(bodyData, 0, sizeof(bodyData)); snprintf(bodyData, sizeof(bodyData), "%.*s", ( int ) body.size( ), body.data()); - auto json_string = uobject::add(request->get_path_parameter("mcollection"), jsonObject, bodyData); + auto json_string = uobject.add(request->get_path_parameter("mcollection"), jsonObject, bodyData); session->close( OK, json_string, { { "Content-Length", ::to_string(json_string.length()) }, { "Content-Type", "application/json" } @@ -338,44 +329,46 @@ void UmosapiService::addUObject( const shared_ptr session ){ } ); } -void UmosapiService::deleteUObject( const shared_ptr session ){ +void UmosapiService::Api::deleteUObject( const shared_ptr< restbed::Session > session ){ + UmosapiService::uobject uobject; auto jsonObject = json_object_new_object(); const auto request = session->get_request(); - auto json_string = uobject::remove(request->get_path_parameter("mcollection"), request->get_path_parameter("oid"), jsonObject); + auto json_string = uobject.remove(request->get_path_parameter("mcollection"), request->get_path_parameter("oid"), jsonObject); session->close( OK, json_string, { - { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); json_object_put(jsonObject); } -void UmosapiService::searchUObjectByKeyValue( const shared_ptr session ){ +void UmosapiService::Api::searchUObjectByKeyValue( const shared_ptr< restbed::Session > session ){ + UmosapiService::uobject uobject; auto jsonObject = json_object_new_array(); const auto request = session->get_request(); - auto json_string = uobject::searchKeyValue(request->get_path_parameter("mcollection"), request->get_path_parameter("key"), request->get_path_parameter("value"), jsonObject); + auto json_string = uobject.searchKeyValue(request->get_path_parameter("mcollection"), request->get_path_parameter("key"), request->get_path_parameter("value"), jsonObject); session->close( OK, json_string, { - { "Content-Length", ::to_string(json_string.length()) }, + { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); json_object_put(jsonObject); } -void UmosapiService::swaggerEndpoint( const shared_ptr session ){ +void UmosapiService::Api::swaggerEndpoint( const shared_ptr< restbed::Session > session ){ const auto request = session->get_request(); ifstream stream(config["swaggerui"] + "/index.html", ifstream::in ); if ( stream.is_open() ) { - const string body = string( istreambuf_iterator< char >(stream), istreambuf_iterator< char>()); + const std::string body = std::string( istreambuf_iterator< char >(stream), istreambuf_iterator< char>()); - const multimap< string, string> headers { + const multimap< std::string, std::string> headers { { "Content-Type", "text/html" }, - { "Content-Length", ::to_string( body.length() ) } + { "Content-Length", std::to_string( body.length() ) } }; session->close(OK, body, headers); } else { @@ -383,20 +376,20 @@ void UmosapiService::swaggerEndpoint( const shared_ptr session ){ } } -void UmosapiService::swaggerEndpointResources( const shared_ptr< Session > session ) +void UmosapiService::Api::swaggerEndpointResources( const shared_ptr< restbed::Session > session ) { const auto request = session->get_request( ); - const string filename = request->get_path_parameter( "filename" ); + const std::string filename = request->get_path_parameter( "filename" ); ifstream stream( config["swaggerui"] + "/" + filename, ifstream::in ); if ( stream.is_open( ) ) { - const string body = string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); + const std::string body = std::string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); - const multimap< string, string > headers + const multimap< std::string, std::string > headers { - { "Content-Length", ::to_string( body.length( ) ) } + { "Content-Length", std::to_string( body.length( ) ) } }; session->close( OK, body, headers ); @@ -407,22 +400,22 @@ void UmosapiService::swaggerEndpointResources( const shared_ptr< Session > sessi } } -void UmosapiService::swaggerEndpointApi( const shared_ptr< Session > session ) +void UmosapiService::Api::swaggerEndpointApi( const shared_ptr< restbed::Session > session ) { const auto request = session->get_request( ); - const string filename = request->get_path_parameter( "filename" ); - const string path = request->get_path(); + const std::string filename = request->get_path_parameter( "filename" ); + const std::string path = request->get_path(); ifstream stream( config["swaggerui"] + "/swagger.json", ifstream::in ); if ( stream.is_open( ) ) { - const string body = string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); + const std::string body = std::string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); - const multimap< string, string > headers + const multimap< std::string, std::string > headers { { "Content-Type", "application/json" }, - { "Content-Length", ::to_string( body.length( ) ) } + { "Content-Length", std::to_string( body.length( ) ) } }; session->close( OK, body, headers ); diff --git a/api/umosapi.h b/api/umosapi.h index a1765d7..3cb2b47 100644 --- a/api/umosapi.h +++ b/api/umosapi.h @@ -16,6 +16,8 @@ using namespace std; using json = nlohmann::json; +namespace UmosapiService { + struct tag { std::string name; std::string description; @@ -53,11 +55,11 @@ struct Paths { std::vector paths; }; -class UmosapiService { +class Api { public: - UmosapiService(); - virtual ~UmosapiService() {}; + Api(); + virtual ~Api() {}; void init(); @@ -105,4 +107,5 @@ class UmosapiService { void swagger(std::string ui_path, std::string swagger_dir, std::string api_path); }; +} #endif -- cgit v1.2.1 From 260ce7465a66427832da15caae0077323dc9750a Mon Sep 17 00:00:00 2001 From: neodarz Date: Mon, 9 Sep 2019 17:56:09 +0200 Subject: Refactoring a little more --- api/umosapi.cpp | 82 ++++++++++++++++++++++++++++----------------------------- api/umosapi.h | 37 +++++++++----------------- 2 files changed, 54 insertions(+), 65 deletions(-) (limited to 'api') diff --git a/api/umosapi.cpp b/api/umosapi.cpp index 6b25124..57716e9 100644 --- a/api/umosapi.cpp +++ b/api/umosapi.cpp @@ -34,21 +34,21 @@ void UmosapiService::Api::init() { auto uri = mongocxx::uri{config["mongoURI"]}; mongo.configure(std::move(uri)); UmosapiService::Api::createResource(); - ofstream swagger_json; + std::ofstream swagger_json; swagger_json.open(config["swaggerui"] + "/swagger.json"); swagger_json << UmosapiService::Api::_swagger.dump(); swagger_json.close(); } void UmosapiService::Api::start(int port, int thr) { - auto settings = make_shared< restbed::Settings >(); + auto settings = std::make_shared< restbed::Settings >(); settings->set_port( port ); settings->set_worker_limit( thr ); settings->set_default_header("Connection", "close"); UmosapiService::Api::_service.start(settings); } -void service_error_handler( const int, const exception& e, const shared_ptr< restbed::Session > session ) +void service_error_handler( const int, const std::exception& e, const std::shared_ptr< restbed::Session > session ) { std::string message = "Backend Service is dead: "; message += e.what(); @@ -60,7 +60,7 @@ void service_error_handler( const int, const exception& e, const shared_ptr< res fprintf( stderr, "ERROR: %s.\n", message.c_str() ); } -void resource_error_handler( const int, const exception& e, const shared_ptr< restbed::Session > session ) +void resource_error_handler( const int, const std::exception& e, const std::shared_ptr< restbed::Session > session ) { std::string message = "Backend Resource is dead: "; message += e.what(); @@ -69,14 +69,14 @@ void resource_error_handler( const int, const exception& e, const shared_ptr< re fprintf( stderr, "ERROR: %s.\n", message.c_str() ); } -void faulty_method_handler( const shared_ptr< restbed::Session > ) +void faulty_method_handler( const std::shared_ptr< restbed::Session > ) { - throw SERVICE_UNAVAILABLE; + throw restbed::SERVICE_UNAVAILABLE; } -void is_ready(const shared_ptr< restbed::Session > session) +void is_ready(const std::shared_ptr< restbed::Session > session) { - session->close( OK, "1", { { "Content-Length", "1"}}); + session->close( restbed::OK, "1", { { "Content-Length", "1"}}); } /* @@ -89,7 +89,7 @@ void is_ready(const shared_ptr< restbed::Session > session) * tags: array of tags */ void UmosapiService::Api::desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< restbed::Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr< restbed::Session >) >& error_callback, tag tags[]) { - auto resource = make_shared< restbed::Resource > (); + auto resource = std::make_shared< restbed::Resource > (); resource->set_path(route); resource->set_method_handler(http_word, callback); resource->set_error_handler( error_callback ); @@ -133,7 +133,7 @@ void UmosapiService::Api::scheme(std::string scheme) { } void UmosapiService::Api::set_path(std::string route) { - UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource = std::make_shared< restbed::Resource > (); UmosapiService::Api::_resource->set_path(route); std::regex parameter(":.*?}"); std::regex base_path("^/v2"); @@ -220,17 +220,17 @@ void UmosapiService::Api::response(std::string http_code, std::string descriptio } void UmosapiService::Api::swagger(std::string ui_path, std::string swagger_dir, std::string api_path) { - UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource = std::make_shared< restbed::Resource > (); UmosapiService::Api::_resource->set_path(ui_path); UmosapiService::Api::_resource->set_method_handler("GET", swaggerEndpoint); UmosapiService::Api::_service.publish(_resource); - UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource = std::make_shared< restbed::Resource > (); UmosapiService::Api::_resource->set_path(ui_path + "/{filename: .*}"); UmosapiService::Api::_resource->set_method_handler("GET", swaggerEndpointResources); UmosapiService::Api::_service.publish(_resource); - UmosapiService::Api::_resource = make_shared< restbed::Resource > (); + UmosapiService::Api::_resource = std::make_shared< restbed::Resource > (); UmosapiService::Api::_resource->set_path(api_path); UmosapiService::Api::_resource->set_method_handler("GET", swaggerEndpointApi); UmosapiService::Api::_service.publish(_resource); @@ -294,13 +294,13 @@ void UmosapiService::Api::createResource() { UmosapiService::Api::_service.set_error_handler( service_error_handler ); } -void UmosapiService::Api::retrieveAll( const shared_ptr< restbed::Session> session ){ +void UmosapiService::Api::retrieveAll( const std::shared_ptr< restbed::Session> session ){ UmosapiService::uobject uobject; auto jsonObjects = json_object_new_array(); const auto& request = session->get_request( ); auto json_string = uobject.retrieveAll(request->get_path_parameter( "mcollection" ), jsonObjects); - session->close( OK, json_string, { + session->close( restbed::OK, json_string, { { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); @@ -308,12 +308,12 @@ void UmosapiService::Api::retrieveAll( const shared_ptr< restbed::Session> sessi } -void UmosapiService::Api::addUObject( const shared_ptr< restbed::Session > session ){ +void UmosapiService::Api::addUObject( const std::shared_ptr< restbed::Session > session ){ const auto request = session->get_request(); size_t content_length = request->get_header( "Content-Length", 0 ); - session->fetch( content_length, [ request ]( const shared_ptr< restbed::Session > session, const Bytes & body ) + session->fetch( content_length, [ request ]( const std::shared_ptr< restbed::Session > session, const restbed::Bytes & body ) { UmosapiService::uobject uobject; auto jsonObject = json_object_new_object(); @@ -321,15 +321,15 @@ void UmosapiService::Api::addUObject( const shared_ptr< restbed::Session > sessi memset(bodyData, 0, sizeof(bodyData)); snprintf(bodyData, sizeof(bodyData), "%.*s", ( int ) body.size( ), body.data()); auto json_string = uobject.add(request->get_path_parameter("mcollection"), jsonObject, bodyData); - session->close( OK, json_string, { - { "Content-Length", ::to_string(json_string.length()) }, + session->close( restbed::OK, json_string, { + { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); json_object_put(jsonObject); } ); } -void UmosapiService::Api::deleteUObject( const shared_ptr< restbed::Session > session ){ +void UmosapiService::Api::deleteUObject( const std::shared_ptr< restbed::Session > session ){ UmosapiService::uobject uobject; auto jsonObject = json_object_new_object(); @@ -337,91 +337,91 @@ void UmosapiService::Api::deleteUObject( const shared_ptr< restbed::Session > se auto json_string = uobject.remove(request->get_path_parameter("mcollection"), request->get_path_parameter("oid"), jsonObject); - session->close( OK, json_string, { + session->close( restbed::OK, json_string, { { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); json_object_put(jsonObject); } -void UmosapiService::Api::searchUObjectByKeyValue( const shared_ptr< restbed::Session > session ){ +void UmosapiService::Api::searchUObjectByKeyValue( const std::shared_ptr< restbed::Session > session ){ UmosapiService::uobject uobject; auto jsonObject = json_object_new_array(); const auto request = session->get_request(); auto json_string = uobject.searchKeyValue(request->get_path_parameter("mcollection"), request->get_path_parameter("key"), request->get_path_parameter("value"), jsonObject); - session->close( OK, json_string, { + session->close( restbed::OK, json_string, { { "Content-Length", std::to_string(json_string.length()) }, { "Content-Type", "application/json" } }); json_object_put(jsonObject); } -void UmosapiService::Api::swaggerEndpoint( const shared_ptr< restbed::Session > session ){ +void UmosapiService::Api::swaggerEndpoint( const std::shared_ptr< restbed::Session > session ){ const auto request = session->get_request(); - ifstream stream(config["swaggerui"] + "/index.html", ifstream::in ); + std::ifstream stream(config["swaggerui"] + "/index.html", std::ifstream::in ); if ( stream.is_open() ) { - const std::string body = std::string( istreambuf_iterator< char >(stream), istreambuf_iterator< char>()); + const std::string body = std::string( std::istreambuf_iterator< char >(stream), std::istreambuf_iterator< char>()); - const multimap< std::string, std::string> headers { + const std::multimap< std::string, std::string> headers { { "Content-Type", "text/html" }, { "Content-Length", std::to_string( body.length() ) } }; - session->close(OK, body, headers); + session->close(restbed::OK, body, headers); } else { - session->close( NOT_FOUND ); + session->close( restbed::NOT_FOUND ); } } -void UmosapiService::Api::swaggerEndpointResources( const shared_ptr< restbed::Session > session ) +void UmosapiService::Api::swaggerEndpointResources( const std::shared_ptr< restbed::Session > session ) { const auto request = session->get_request( ); const std::string filename = request->get_path_parameter( "filename" ); - ifstream stream( config["swaggerui"] + "/" + filename, ifstream::in ); + std::ifstream stream( config["swaggerui"] + "/" + filename, std::ifstream::in ); if ( stream.is_open( ) ) { - const std::string body = std::string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); + const std::string body = std::string( std::istreambuf_iterator< char >( stream ), std::istreambuf_iterator< char >( ) ); - const multimap< std::string, std::string > headers + const std::multimap< std::string, std::string > headers { { "Content-Length", std::to_string( body.length( ) ) } }; - session->close( OK, body, headers ); + session->close( restbed::OK, body, headers ); } else { - session->close( NOT_FOUND ); + session->close( restbed::NOT_FOUND ); } } -void UmosapiService::Api::swaggerEndpointApi( const shared_ptr< restbed::Session > session ) +void UmosapiService::Api::swaggerEndpointApi( const std::shared_ptr< restbed::Session > session ) { const auto request = session->get_request( ); const std::string filename = request->get_path_parameter( "filename" ); const std::string path = request->get_path(); - ifstream stream( config["swaggerui"] + "/swagger.json", ifstream::in ); + std::ifstream stream( config["swaggerui"] + "/swagger.json", std::ifstream::in ); if ( stream.is_open( ) ) { - const std::string body = std::string( istreambuf_iterator< char >( stream ), istreambuf_iterator< char >( ) ); + const std::string body = std::string( std::istreambuf_iterator< char >( stream ), std::istreambuf_iterator< char >( ) ); - const multimap< std::string, std::string > headers + const std::multimap< std::string, std::string > headers { { "Content-Type", "application/json" }, { "Content-Length", std::to_string( body.length( ) ) } }; - session->close( OK, body, headers ); + session->close( restbed::OK, body, headers ); } else { - session->close( NOT_FOUND ); + session->close( restbed::NOT_FOUND ); } } diff --git a/api/umosapi.h b/api/umosapi.h index 3cb2b47..a066ac9 100644 --- a/api/umosapi.h +++ b/api/umosapi.h @@ -1,21 +1,10 @@ #ifndef UmosapiService_H_ #define UmosapiService_H_ -//#include -//#include -//#include - #include -//#include - #include -using namespace restbed; -using namespace std; - -using json = nlohmann::json; - namespace UmosapiService { struct tag { @@ -64,30 +53,30 @@ class Api { void init(); void start(int, int); - Service _service; - json _swagger; - vector _tags; + restbed::Service _service; + nlohmann::json _swagger; + std::vector _tags; private: - void desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback, tag tags[]); + void desc(std::string route, std::string http_word, const std::function< void ( const std::shared_ptr< restbed::Session > ) >& callback, const std::function< void(int, const std::exception&, std::shared_ptr< restbed::Session >) >& error_callback, tag tags[]); void createResource(); - static void retrieveAll( const shared_ptr session ); - static void addUObject( const shared_ptr session ); - static void deleteUObject( const shared_ptr session ); - static void searchUObjectByKeyValue( const shared_ptr session ); - static void swaggerEndpoint( const shared_ptr session ); - static void swaggerEndpointResources( const shared_ptr session ); - static void swaggerEndpointApi( const shared_ptr session ); + static void retrieveAll( const std::shared_ptr< restbed::Session > session ); + static void addUObject( const std::shared_ptr< restbed::Session > session ); + static void deleteUObject( const std::shared_ptr< restbed::Session > session ); + static void searchUObjectByKeyValue( const std::shared_ptr< restbed::Session > session ); + static void swaggerEndpoint( const std::shared_ptr< restbed::Session > session ); + static void swaggerEndpointResources( const std::shared_ptr< restbed::Session > session ); + static void swaggerEndpointApi( const std::shared_ptr< restbed::Session > session ); - shared_ptr< Resource> _resource; + std::shared_ptr< restbed::Resource> _resource; Definition _definition; Definitions _definitions; Path _path; Paths _paths; void set_path(); void set_path(std::string route); - void set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< Session > ) >& callback); + void set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< restbed::Session > ) >& callback); void set_error_handler(const std::function< void(int, const std::exception&, std::shared_ptr) >& error_callback); void produce(std::string); void consume(std::string); -- cgit v1.2.1 From cc8c1ad450667c8f6f983ba4f0d640accdcb49cf Mon Sep 17 00:00:00 2001 From: neodarz Date: Tue, 10 Sep 2019 10:26:16 +0200 Subject: Little refactorisation --- api/umosapi.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/umosapi.cpp b/api/umosapi.cpp index 57716e9..f5d7003 100644 --- a/api/umosapi.cpp +++ b/api/umosapi.cpp @@ -146,9 +146,7 @@ void UmosapiService::Api::set_path(std::string route) { void UmosapiService::Api::set_method_handler(std::string http_word, const std::function< void ( const std::shared_ptr< restbed::Session > ) >& callback) { UmosapiService::Api::_resource->set_method_handler(http_word, callback); std::locale loc; - for (auto& c : http_word) { - c = tolower(c); - } + for (auto& c : http_word) { c = tolower(c); } UmosapiService::Api::_path.words.push_back(HttpWord{http_word}); UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word]["description"] = ""; UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word]["operationId"] = ""; @@ -160,7 +158,7 @@ void UmosapiService::Api::set_error_handler(const std::function< void(int, const } void UmosapiService::Api::publish() { - for (auto& http_word: UmosapiService::Api::_path.words) { + for (const auto& http_word: UmosapiService::Api::_path.words) { auto responses = UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word.name]["responses"]; if (responses.find("200") == responses.end()) { UmosapiService::Api::_swagger["paths"][UmosapiService::Api::_path.name][http_word.name]["responses"]["200"]["description"] = "All is fine."; @@ -202,7 +200,7 @@ void UmosapiService::Api::parameter(std::string name, std::string description, s parameter["in"] = "path"; } else { parameter["in"] = "body"; - for (auto& def: UmosapiService::Api::_definitions.defs) { + for (const auto& def: UmosapiService::Api::_definitions.defs) { if (def.name == schema ) { std::string schema_path = "#/definitions/"; parameter["schema"]["$ref"] = schema_path.append(schema); -- cgit v1.2.1