From b1754e4e6506d0809e18ed979d4e30a6277c6d25 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Tue, 19 Jan 2016 15:06:27 +0100 Subject: [PATCH] Web interface: Use rapidjson when creating responses --- spectrum_manager/src/APIServer.cpp | 63 ++++++++++++++++++------------ spectrum_manager/src/APIServer.h | 7 +++- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/spectrum_manager/src/APIServer.cpp b/spectrum_manager/src/APIServer.cpp index 8dd645c3..0f882222 100644 --- a/spectrum_manager/src/APIServer.cpp +++ b/spectrum_manager/src/APIServer.cpp @@ -12,9 +12,12 @@ #include #include +#include "rapidjson/rapidjson.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + #define ALLOW_ONLY_ADMIN() if (!session->admin) { \ - std::string _json = "{\"error\":1, \"message\": \"Only administrators can do this API call.\"}"; \ - send_json(conn, _json); \ + send_ack(conn, true, "Only administrators can do this API call."); \ return; \ } @@ -48,13 +51,12 @@ APIServer::APIServer(ManagerConfig *config, StorageBackend *storage) { APIServer::~APIServer() { } -std::string &APIServer::safe_arg(std::string &arg) { - boost::replace_all(arg, "\n", ""); - boost::replace_all(arg, "\"", "'"); - return arg; -} +void APIServer::send_json(struct mg_connection *conn, const Document &d) { + StringBuffer buffer; + Writer writer(buffer); + d.Accept(writer); + std::string json(buffer.GetString()); -void APIServer::send_json(struct mg_connection *conn, const std::string &json) { std::cout << "Sending JSON:\n"; std::cout << json << "\n"; mg_printf(conn, @@ -66,6 +68,15 @@ void APIServer::send_json(struct mg_connection *conn, const std::string &json) { (int) json.size(), json.c_str()); } +void APIServer::send_ack(struct mg_connection *conn, bool error, const std::string &message) { + Document json; + json.SetObject(); + json.AddMember("error", error, json.GetAllocator()); + json.AddMember("message", message.c_str(), json.GetAllocator()); + + send_json(conn, json); +} + void APIServer::serve_instances(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) { // std::string jid = get_http_var(hm, "jid"); // if (!jid.empty()) { @@ -75,32 +86,36 @@ void APIServer::serve_instances(Server *server, Server::session *session, struct std::vector list = show_list(m_config, false); - std::string json = "{\"error\":0, \"instances\": ["; + Document json; + json.SetObject(); + json.AddMember("error", 0, json.GetAllocator()); - BOOST_FOREACH(std::string &instance, list) { - json += "{"; - json += "\"id\":\"" + instance + "\","; - json += "\"name\":\"" + instance + "\","; + Value instances(kArrayType); + BOOST_FOREACH(std::string &id, list) { + Value instance; + instance.SetObject(); + instance.AddMember("id", id.c_str(), json.GetAllocator()); + instance.AddMember("name", id.c_str(), json.GetAllocator()); - std::string status = server->send_command(instance, "status"); + std::string status = server->send_command(id, "status"); if (status.empty()) { status = "Cannot get the instance status."; } else if (*(status.end() - 1) == '\n') { status.erase(status.end() - 1); } - json += "\"status\":\"" + safe_arg(status) + "\","; + instance.AddMember("status", status.c_str(), json.GetAllocator()); bool running = true; if (status.find("Running") == std::string::npos) { running = false; } - json += "\"running\":" + (running ? std::string("1") : std::string("0")); - json += "},"; - } - json.erase(json.end() - 1); + instance.AddMember("running", running, json.GetAllocator()); - json += "]}"; + instances.PushBack(instance, json.GetAllocator()); + } + + json.AddMember("instances", instances, json.GetAllocator()); send_json(conn, json); } @@ -111,13 +126,11 @@ void APIServer::serve_instances_start(Server *server, Server::session *session, std::string instance = uri.substr(uri.rfind("/") + 1); start_instances(m_config, instance); std::string response = get_response(); - std::string error = response.find("OK") == std::string::npos ? "1" : "0"; - std::string json = "{\"error\":" + error + ", \"message\": \"" + safe_arg(response) + "\"}"; // TODO: So far it needs some time to reload Spectrum 2, so just sleep here. sleep(1); - send_json(conn, json); + send_ack(conn, response.find("OK") == std::string::npos, response); } void APIServer::serve_instances_stop(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) { @@ -127,9 +140,7 @@ void APIServer::serve_instances_stop(Server *server, Server::session *session, s std::string instance = uri.substr(uri.rfind("/") + 1); stop_instances(m_config, instance); std::string response = get_response(); - std::string error = response.find("OK") == std::string::npos ? "1" : "0"; - std::string json = "{\"error\":" + error + ", \"message\": \"" + safe_arg(response) + "\"}"; \ - send_json(conn, json); + send_ack(conn, response.find("OK") == std::string::npos, response); } void APIServer::handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm) { diff --git a/spectrum_manager/src/APIServer.h b/spectrum_manager/src/APIServer.h index c90714a7..d1b047e2 100644 --- a/spectrum_manager/src/APIServer.h +++ b/spectrum_manager/src/APIServer.h @@ -28,6 +28,8 @@ #include #include +#include "rapidjson/document.h" + #include "mongoose.h" #include "managerconfig.h" #include "server.h" @@ -39,6 +41,7 @@ #include "transport/StorageBackend.h" using namespace Transport; +using namespace rapidjson; class APIServer { public: @@ -52,8 +55,8 @@ class APIServer { void serve_instances(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm); void serve_instances_start(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm); void serve_instances_stop(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm); - std::string &safe_arg(std::string &); - void send_json(struct mg_connection *conn, const std::string &json); + void send_json(struct mg_connection *conn, const Document &d); + void send_ack(struct mg_connection *conn, bool error, const std::string &message); private: ManagerConfig *m_config;