Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

Commit

Permalink
feat(http): print help info on root path of the http server (#367)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wu Tao authored Dec 26, 2019
1 parent b0af591 commit c3f2cd4
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 42 deletions.
42 changes: 37 additions & 5 deletions include/dsn/tool-api/http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,37 +60,69 @@ class http_service

virtual std::string path() const = 0;

void register_handler(std::string path, http_callback cb)
void register_handler(std::string path, http_callback cb, std::string help)
{
_cb_map.emplace(std::move(path), std::move(cb));
_cb_map.emplace(std::move(path), std::make_pair(std::move(cb), std::move(help)));
}

void call(const http_request &req, http_response &resp)
{
auto it = _cb_map.find(req.service_method.second);
if (it != _cb_map.end()) {
it->second(req, resp);
it->second.first(req, resp);
} else {
resp.status_code = http_status_code::not_found;
resp.body = std::string("method not found for \"") + req.service_method.second + "\"";
}
}

struct method_help_entry
{
std::string name;
std::string help;
};
std::vector<method_help_entry> get_help() const
{
std::vector<method_help_entry> ret;
ret.reserve(_cb_map.size());
for (const auto &method : _cb_map) {
ret.push_back({method.first, method.second.second});
}
return ret;
}

private:
std::map<std::string, http_callback> _cb_map;
std::map<std::string, std::pair<http_callback, std::string>> _cb_map;
};

class http_server : public serverlet<http_server>
{
public:
http_server();
explicit http_server(bool start = true);

~http_server() override = default;

void add_service(http_service *service);

void serve(message_ex *msg);

struct service_method_help_entry
{
std::string name;
std::string method;
std::string help;
};
std::vector<service_method_help_entry> get_help() const
{
std::vector<service_method_help_entry> ret;
for (const auto &service : _service_map) {
for (const auto &method : service.second->get_help()) {
ret.push_back({service.first, method.name, method.help});
}
}
return ret;
}

private:
std::map<std::string, std::unique_ptr<http_service>> _service_map;
};
Expand Down
8 changes: 6 additions & 2 deletions src/dist/http/http_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@ namespace dsn {
}
}

http_server::http_server() : serverlet<http_server>("http_server")
http_server::http_server(bool start /*default=true*/) : serverlet<http_server>("http_server")
{
if (!start) {
return;
}

register_rpc_handler(RPC_HTTP_SERVICE, "http_service", &http_server::serve);

tools::register_message_header_parser<http_message_parser>(NET_HDR_HTTP, {"GET ", "POST"});

// add builtin services
add_service(new root_http_service());
add_service(new root_http_service(this));

#ifdef DSN_ENABLE_GPERF
add_service(new pprof_http_service());
Expand Down
4 changes: 2 additions & 2 deletions src/dist/http/perf_counter_http_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class perf_counter_http_service : public http_service
public:
perf_counter_http_service()
{
// GET ip:port/perfCounter?name={perf_counter_name}
register_handler("",
std::bind(&perf_counter_http_service::get_perf_counter_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
std::placeholders::_2),
"ip:port/perfCounter?name={perf_counter_name}");
}

std::string path() const override { return "perfCounter"; }
Expand Down
24 changes: 10 additions & 14 deletions src/dist/http/pprof_http_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,36 @@ class pprof_http_service : public http_service
public:
pprof_http_service()
{
// ip:port/pprof/heap
register_handler("heap",
std::bind(&pprof_http_service::heap_handler,
this,
std::placeholders::_1,
std::placeholders::_2));

// ip:port/pprof/symbol
std::placeholders::_2),
"ip:port/pprof/heap");
register_handler("symbol",
std::bind(&pprof_http_service::symbol_handler,
this,
std::placeholders::_1,
std::placeholders::_2));

// ip:port/pprof/cmdline
std::placeholders::_2),
"ip:port/pprof/symbol");
register_handler("cmdline",
std::bind(&pprof_http_service::cmdline_handler,
this,
std::placeholders::_1,
std::placeholders::_2));

// ip:port/pprof/growth
std::placeholders::_2),
"ip:port/pprof/cmdline");
register_handler("growth",
std::bind(&pprof_http_service::growth_handler,
this,
std::placeholders::_1,
std::placeholders::_2));

// ip:port/pprof/profile
std::placeholders::_2),
"ip:port/pprof/growth");
register_handler("profile",
std::bind(&pprof_http_service::profile_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
std::placeholders::_2),
"ip:port/pprof/profile");
}

std::string path() const override { return "pprof"; }
Expand Down
20 changes: 17 additions & 3 deletions src/dist/http/root_http_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,44 @@
// can be found in the LICENSE file in the root directory of this source tree.

#include <dsn/tool-api/http_server.h>
#include <dsn/utility/output_utils.h>
#include <string>

namespace dsn {

class root_http_service : public http_service
{
public:
root_http_service()
explicit root_http_service(http_server *server) : _server(server)
{
// url: ip:port/
register_handler("",
std::bind(&root_http_service::default_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
std::placeholders::_2),
"ip:port/");
}

std::string path() const override { return ""; }

void default_handler(const http_request &req, http_response &resp)
{
resp.body = "hello world";
utils::table_printer tp;
std::ostringstream oss;
auto help_entries = _server->get_help();
for (const auto &ent : help_entries) {
tp.add_row_name_and_data(std::string("/") + ent.name + (ent.method.empty() ? "" : "/") +
ent.method,
ent.help);
}
tp.output(oss, utils::table_printer::output_format::kJsonCompact);
resp.body = oss.str();
resp.status_code = http_status_code::ok;
}

private:
http_server *_server;
};

} // namespace dsn
8 changes: 4 additions & 4 deletions src/dist/http/server_info_http_services.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class version_http_service : public http_service
public:
version_http_service()
{
// GET ip:port/version
register_handler("",
std::bind(&version_http_service::get_version_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
std::placeholders::_2),
"ip:port/version");
}

std::string path() const override { return "version"; }
Expand All @@ -39,12 +39,12 @@ class recent_start_time_http_service : public http_service
public:
recent_start_time_http_service()
{
// GET ip:port/recentStartTime
register_handler("",
std::bind(&recent_start_time_http_service::get_recent_start_time_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
std::placeholders::_2),
"ip:port/recentStartTime");
}

std::string path() const override { return "recentStartTime"; }
Expand Down
22 changes: 22 additions & 0 deletions src/dist/http/test/http_server_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <gtest/gtest.h>

#include "dist/http/http_message_parser.h"
#include "dist/http/root_http_service.h"
#include "dist/http/server_info_http_services.h"

namespace dsn {

Expand Down Expand Up @@ -42,6 +44,26 @@ TEST(http_server, parse_url)
}
}

TEST(root_http_service_test, get_help)
{
http_server server(false);
auto root = new root_http_service(&server);
server.add_service(root);
ASSERT_EQ(server.get_help().size(), 1);

http_request req;
http_response resp;
root->default_handler(req, resp);
ASSERT_EQ(resp.status_code, http_status_code::ok);
ASSERT_EQ(resp.body, "{\"/\":\"ip:port/\"}\n");

auto ver = new version_http_service();
server.add_service(ver);
ASSERT_EQ(server.get_help().size(), 2);
root->default_handler(req, resp);
ASSERT_EQ(resp.body, "{\"/\":\"ip:port/\",\"/version\":\"ip:port/version\"}\n");
}

class http_message_parser_test : public testing::Test
{
public:
Expand Down
24 changes: 12 additions & 12 deletions src/dist/replication/meta_server/meta_http_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,42 @@ class meta_http_service : public http_service
public:
explicit meta_http_service(meta_service *s) : _service(s)
{
// GET ip:port/meta/app?app_name=temp
register_handler("app",
std::bind(&meta_http_service::get_app_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
// GET ip:port/meta/apps
std::placeholders::_2),
"ip:port/meta/app?app_name=temp");
register_handler("apps",
std::bind(&meta_http_service::list_app_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
// GET ip:port/meta/nodes
std::placeholders::_2),
"ip:port/meta/apps");
register_handler("nodes",
std::bind(&meta_http_service::list_node_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
// GET ip:port/meta/cluster
std::placeholders::_2),
"ip:port/meta/nodes");
register_handler("cluster",
std::bind(&meta_http_service::get_cluster_info_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
// GET ip:port/meta/app_envs?name=temp
std::placeholders::_2),
"ip:port/meta/cluster");
register_handler("app_envs",
std::bind(&meta_http_service::get_app_envs_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
// GET ip:port/meta/backup_policy
std::placeholders::_2),
"ip:port/meta/app_envs?name=temp");
register_handler("backup_policy",
std::bind(&meta_http_service::query_backup_policy_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
std::placeholders::_2),
"ip:port/meta/backup_policy");
}

std::string path() const override { return "meta"; }
Expand Down

0 comments on commit c3f2cd4

Please sign in to comment.