manager: /api/v1/instances returns the list of instances

This commit is contained in:
Jan Kaluza 2016-01-18 14:43:37 +01:00
parent 737aa148da
commit a71462650e
4 changed files with 191 additions and 28 deletions

View file

@ -0,0 +1,92 @@
#include "APIServer.h"
#include "methods.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <pthread.h>
#include <fstream>
#include <string>
#include <cerrno>
static std::string get_http_var(const struct http_message *hm, const char *name) {
char data[4096];
data[0] = '\0';
mg_get_http_var(&hm->body, name, data, sizeof(data));
if (data[0] != '\0') {
return data;
}
mg_get_http_var(&hm->query_string, name, data, sizeof(data));
if (data[0] != '\0') {
return data;
}
return "";
}
APIServer::APIServer(ManagerConfig *config, StorageBackend *storage) {
m_config = config;
m_storage = storage;
}
APIServer::~APIServer() {
}
void APIServer::send_json(struct mg_connection *conn, const std::string &json) {
mg_printf(conn,
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/json\r\n"
"Content-Length: %d\r\n"
"\r\n"
"%s",
(int) json.size(), json.c_str());
}
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()) {
// serve_instance(conn, hm, jid);
// return;
// }
std::vector<std::string> list = show_list(m_config, false);
std::string json = "{\"error\":0, \"instances\": [";
BOOST_FOREACH(std::string &instance, list) {
json += "{";
json += "\"id\":\"" + instance + "\",";
json += "\"name\":\"" + instance + "\",";
std::string status = server->send_command(instance, "status");
if (status.empty()) {
status = "Cannot get the instance status.";
}
else if (*(status.end() - 1) == '\n') {
status.erase(status.end() - 1);
}
json += "\"status\":\"" + status + "\"";
json += "},";
}
json.erase(json.end() - 1);
json += "]}";
send_json(conn, json);
}
void APIServer::handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm) {
if (mg_vcmp(&hm->uri, "/api/v1/instances") == 0) {
serve_instances(server, sess, conn, hm);
}
}

View file

@ -0,0 +1,58 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2016, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#pragma once
#include <boost/program_options.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/assign.hpp>
#include <boost/bind.hpp>
#include <boost/signal.hpp>
#include "mongoose.h"
#include "managerconfig.h"
#include "server.h"
#include "transport/Config.h"
#include "transport/SQLite3Backend.h"
#include "transport/MySQLBackend.h"
#include "transport/PQXXBackend.h"
#include "transport/StorageBackend.h"
using namespace Transport;
class APIServer {
public:
APIServer(ManagerConfig *config, StorageBackend *storage);
virtual ~APIServer();
void handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
private:
void serve_instances(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
void send_json(struct mg_connection *conn, const std::string &json);
private:
ManagerConfig *m_config;
StorageBackend *m_storage;
};

View file

@ -1,3 +1,4 @@
#include "APIServer.h"
#include "server.h"
#include "methods.h"
@ -99,9 +100,13 @@ Server::Server(ManagerConfig *config, const std::string &config_file) {
m_storage = NULL;
std::cerr << "Can't connect to database!\n";
}
m_apiServer = new APIServer(config, m_storage);
}
Server::~Server() {
delete m_apiServer;
mg_mgr_free(&m_mgr);
if (m_storage) {
delete m_storage;
@ -173,9 +178,10 @@ void Server::authorize(struct mg_connection *conn, struct http_message *hm) {
mg_printf(conn, "HTTP/1.1 302 Found\r\n"
"Set-Cookie: session=%s; max-age=3600; http-only\r\n" // Session ID
"Set-Cookie: user=%s\r\n" // Set user, needed by Javascript code
"Set-Cookie: admin=%s\r\n" // Set user, needed by Javascript code
"Set-Cookie: original_url=/; max-age=0\r\n" // Delete original_url
"Location: /\r\n\r\n",
session->session_id, session->user);
session->session_id, session->user, session->admin ? "1" : "0");
} else {
// Authentication failure, redirect to login.
redirect_to(conn, hm, "/login");
@ -312,9 +318,10 @@ void Server::serve_cmd(struct mg_connection *conn, struct http_message *hm) {
void Server::serve_logout(struct mg_connection *conn, struct http_message *hm) {
Server:session *session = get_session(hm);
mg_printf(conn, "HTTP/1.1 302 Found\r\n"
"Set-Cookie: session=%s; max-age=0\r\n" // Session ID
"Set-Cookie: session=%s; max-age=0\r\n"
"Set-Cookie: admin=%s; max-age=0\r\n"
"Location: /\r\n\r\n",
session->session_id);
session->session_id, session->admin ? "1" : "0");
sessions.erase(session->session_id);
delete session;
@ -675,32 +682,34 @@ void Server::event_handler(struct mg_connection *conn, int ev, void *p) {
redirect_to(conn, hm, "/login");
} else if (mg_vcmp(&hm->uri, "/authorize") == 0) {
authorize(conn, hm);
} else if (mg_vcmp(&hm->uri, "/") == 0) {
serve_instances(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/") == 0) {
// serve_instances(conn, hm);
} else if (mg_vcmp(&hm->uri, "/logout") == 0) {
serve_logout(conn, hm);
} else if (mg_vcmp(&hm->uri, "/instances") == 0) {
serve_instances(conn, hm);
} else if (mg_vcmp(&hm->uri, "/onlineusers") == 0) {
serve_onlineusers(conn, hm);
} else if (mg_vcmp(&hm->uri, "/cmd") == 0) {
serve_cmd(conn, hm);
} else if (mg_vcmp(&hm->uri, "/instances/start") == 0) {
serve_instances_start(conn, hm);
} else if (mg_vcmp(&hm->uri, "/instances/stop") == 0) {
serve_instances_stop(conn, hm);
} else if (mg_vcmp(&hm->uri, "/instances/register") == 0) {
serve_instances_register(conn, hm);
} else if (mg_vcmp(&hm->uri, "/instances/unregister") == 0) {
serve_instances_unregister(conn, hm);
} else if (mg_vcmp(&hm->uri, "/users") == 0) {
serve_users(conn, hm);
} else if (mg_vcmp(&hm->uri, "/users/add") == 0) {
serve_users_add(conn, hm);
} else if (mg_vcmp(&hm->uri, "/users/remove") == 0) {
serve_users_remove(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/instances") == 0) {
// serve_instances(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/onlineusers") == 0) {
// serve_onlineusers(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/cmd") == 0) {
// serve_cmd(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/instances/start") == 0) {
// serve_instances_start(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/instances/stop") == 0) {
// serve_instances_stop(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/instances/register") == 0) {
// serve_instances_register(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/instances/unregister") == 0) {
// serve_instances_unregister(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/users") == 0) {
// serve_users(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/users/add") == 0) {
// serve_users_add(conn, hm);
// } else if (mg_vcmp(&hm->uri, "/users/remove") == 0) {
// serve_users_remove(conn, hm);
} else if (has_prefix(&hm->uri, "/oauth2")) {
serve_oauth2(conn, hm);
} else if (has_prefix(&hm->uri, "/api/v1/")) {
m_apiServer->handleRequest(this, get_session(hm), conn, hm);
} else {
mg_serve_http(conn, hm, s_http_server_opts);
}

View file

@ -39,6 +39,8 @@
using namespace Transport;
class APIServer;
class Server {
public:
struct session {
@ -59,6 +61,10 @@ class Server {
void event_handler(struct mg_connection *nc, int ev, void *p);
void redirect_to(struct mg_connection *conn, struct http_message *hm, const char *where);
std::string send_command(const std::string &jid, const std::string &cmd);
private:
void serve_instance(struct mg_connection *conn, struct http_message *hm, const std::string &jid);
void serve_instances(struct mg_connection *conn, struct http_message *hm);
@ -74,7 +80,6 @@ class Server {
void serve_cmd(struct mg_connection *conn, struct http_message *hm);
void serve_oauth2(struct mg_connection *conn, struct http_message *hm);
void print_html(struct mg_connection *conn, struct http_message *hm, const std::string &html);
std::string send_command(const std::string &jid, const std::string &cmd);
private:
bool check_password(const std::string &user, const std::string &password);
@ -85,8 +90,6 @@ class Server {
bool is_authorized(const struct mg_connection *conn, struct http_message *hm);
void redirect_to(struct mg_connection *conn, struct http_message *hm, const char *where);
private:
struct mg_mgr m_mgr;
struct mg_connection *m_nc;
@ -99,4 +102,5 @@ class Server {
std::string m_footer;
Config *m_storageCfg;
StorageBackend *m_storage;
APIServer *m_apiServer;
};