From: Waldemar Kozaczuk <jwkozac...@gmail.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

httpserver: replace boost program_options with light options utility functions

Fixes #1053

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
Message-Id: <20191003042437.27978-5-jwkozac...@gmail.com>

---
diff --git a/modules/httpserver-api/global_server.cc b/modules/httpserver-api/global_server.cc
--- a/modules/httpserver-api/global_server.cc
+++ b/modules/httpserver-api/global_server.cc
@@ -17,6 +17,7 @@
 #include "json/api_docs.hh"
 #include <osv/debug.h>
 #include "transformers.hh"
+#include <osv/options.hh>

 namespace httpserver {

@@ -30,12 +31,15 @@ global_server& global_server::get()
     return *instance;
 }

-bool global_server::run(po::variables_map& _config)
+bool global_server::run(std::map<std::string,std::vector<std::string>>& _config)
 {
     if (get().s != nullptr) {
         return false;
     }
- std::string config_file_path = _config["config-file"].as<std::string>();
+    std::string config_file_path = "/tmp/httpserver.conf";
+    if (options::option_value_exists(_config, "config-file")) {
+ config_file_path = options::extract_option_value(_config, "config-file");
+    }
     std::ifstream f(config_file_path);
     if (f.is_open()) {
         try {
@@ -79,11 +83,15 @@ bool global_server::run(po::variables_map& _config)
     set(_config);
     get().set("ipaddress", "0.0.0.0");
     get().set("port", "8000");
-    get().set("cert", "/etc/pki/server.pem");
-    get().set("key", "/etc/pki/private/server.key");
-    get().set("cacert", "/etc/pki/CA/cacert.pem");

-    get().s = new http::server::server(&get().config, &get()._routes);
+    if (get().config.count("ssl")) {
+        get().set("cert", "/etc/pki/server.pem");
+        get().set("key", "/etc/pki/private/server.key");
+        get().set("cacert", "/etc/pki/CA/cacert.pem");
+    }
+
+    auto port = get().config["port"][0];
+    get().s = new http::server::server(get().config, &get()._routes);

     osv::this_application::on_termination_request([&] {
         get().s->close();
@@ -92,7 +100,7 @@ bool global_server::run(po::variables_map& _config)
         }
     });

- std::cout << "Rest API server running on port " << get().config["port"].as<std::string>() << std::endl;
+    std::cout << "Rest API server running on port " << port << std::endl;
     get().s->run();
     return true;
 }
@@ -153,7 +161,7 @@ global_server::global_server()
     set_routes();
 }

-global_server& global_server::set(po::variables_map& _config)
+global_server& global_server::set(std::map<std::string,std::vector<std::string>> &_config)
 {
     for (auto i : _config) {
         get().config.insert(std::make_pair(i.first, i.second));
@@ -164,9 +172,9 @@ global_server& global_server::set(po::variables_map& _config)
 global_server& global_server::set(const std::string& key,
                                   const std::string& _value)
 {
-    boost::any val(_value);
-    boost::program_options::variable_value v(val, false);
-    config.insert(std::make_pair(std::string(key), v));
+    std::vector<std::string> values;
+    values.push_back(_value);
+    config.insert(std::make_pair(std::string(key), values));
     return *this;
 }

diff --git a/modules/httpserver-api/global_server.hh b/modules/httpserver-api/global_server.hh
--- a/modules/httpserver-api/global_server.hh
+++ b/modules/httpserver-api/global_server.hh
@@ -10,13 +10,10 @@
 #include "routes.hh"
 #include "server.hh"
 #include <vector>
-#include <boost/program_options/variables_map.hpp>
 #include <mutex>
 #include <condition_variable>
 #include <external/x64/misc.bin/usr/include/yaml-cpp/node/iterator.h>

-namespace po = boost::program_options;
-
 namespace httpserver {
 /**
  * Global server is a singleton class that controls
@@ -46,7 +43,7 @@ public:
      *
      * @return false if the server already running
      */
-    static bool run(po::variables_map& config);
+ static bool run(std::map<std::string,std::vector<std::string>>& config);

     /**
      * set an entry in the configuration
@@ -73,15 +70,15 @@ private:
     static global_server* instance;
     routes _routes;
     http::server::server* s;
-    po::variables_map config;
+    std::map<std::string,std::vector<std::string>> config;
     std::vector<void*> plugins;

     /**
      * set configuration based on command line.
      * @param config a variable map
      * @return a reference to the server
      */
-    static global_server& set(po::variables_map& config);
+ static global_server& set(std::map<std::string,std::vector<std::string>>& config);

 };

diff --git a/modules/httpserver-api/main.cc b/modules/httpserver-api/main.cc
--- a/modules/httpserver-api/main.cc
+++ b/modules/httpserver-api/main.cc
@@ -10,43 +10,47 @@

 #include "server.hh"

-#include <boost/program_options/options_description.hpp>
-#include <boost/program_options/variables_map.hpp>
-#include <boost/program_options/parsers.hpp>
 #include <boost/asio.hpp>
 #include "global_server.hh"
 #include <osv/exception_utils.hh>
+#include <osv/options.hh>

 using namespace httpserver;

-namespace po = boost::program_options;
+static void usage()
+{
+    std::cout << "Allowed options:\n";
+ std::cout << " --help produce help message\n";
+    std::cout << "  --config-file arg (=/tmp/httpserver.conf)\n";
+ std::cout << " configuration file path\n"; + std::cout << " --access-allow arg Set the Access-Control-Allow-Origin to\n"; + std::cout << " *. Note the security risk\n"; + std::cout << " --ipaddress arg set the ip address\n";
+    std::cout << "  --port arg                            set the port\n";
+ std::cout << " --cert arg path to server's SSL certificate\n"; + std::cout << " --key arg path to server's private key\n"; + std::cout << " --cacert arg path to CA certificate\n";
+    std::cout << "  --ssl                                 enable SSL\n\n";
+}
+
+static void handle_parse_error(const std::string &message)
+{
+    std::cout << message << std::endl;
+    usage();
+    exit(1);
+}

 int main(int argc, char* argv[])
 {
-    po::options_description desc("Allowed options");
-    desc.add_options()
-        ("help", "produce help message")
- ("config-file", po::value<std::string>()->default_value("/tmp/httpserver.conf"), "configuration file path")
-        ("access-allow", po::value<std::string>(),
- "Set the Access-Control-Allow-Origin to *. Note the security risk")
-        ("ipaddress", po::value<std::string>(), "set the ip address")
-        ("port", po::value<std::string>(), "set the port")
- ("cert", po::value<std::string>(), "path to server's SSL certificate")
-        ("key", po::value<std::string>(), "path to server's private key")
-        ("cacert", po::value<std::string>(), "path to CA certificate")
-        ("ssl", "enable SSL");
-
-    po::variables_map config;
-    po::store(po::parse_command_line(argc, argv, desc), config);
-    po::notify(config);
-
-    if (config.count("help")) {
-        std::cerr << desc << "\n";
+ auto options_values = options::parse_options_values(argc - 1, argv + 1, handle_parse_error);
+
+ if (options::extract_option_flag(options_values, "help", handle_parse_error)) {
+        usage();
         return 1;
     }

     try {
-        global_server::run(config);
+        global_server::run(options_values);
     } catch (...) {
         std::cerr << "httpserver failed: " << current_what() << std::endl;
         return 1;
diff --git a/modules/httpserver-api/request_handler.cc b/modules/httpserver-api/request_handler.cc
--- a/modules/httpserver-api/request_handler.cc
+++ b/modules/httpserver-api/request_handler.cc
@@ -20,6 +20,7 @@
 #include <fstream>
 #include <sstream>
 #include <string>
+#include <osv/options.hh>

 namespace http {

@@ -62,13 +63,13 @@ size_t request_handler::update_parameters(request& req)
     return par;
 }

-request_handler::request_handler(httpserver::routes* routes, const boost::program_options::variables_map& _config) +request_handler::request_handler(httpserver::routes* routes, std::map<std::string,std::vector<std::string>>& _config)
     : routes(routes),
       config(_config)

 {
-    if (config.count("access-allow")) {
-        const auto s = config["access-allow"].as<std::string>();
+    if (options::option_value_exists(_config, "access-allow")) {
+ const auto s = options::extract_option_value(_config, "access-allow");

         std::string::size_type b = 0;
         do {
diff --git a/modules/httpserver-api/request_handler.hh b/modules/httpserver-api/request_handler.hh
--- a/modules/httpserver-api/request_handler.hh
+++ b/modules/httpserver-api/request_handler.hh
@@ -15,7 +15,6 @@

 #include "routes.hh"

-#include <boost/program_options/variables_map.hpp>
 #include <string>

 namespace http {
@@ -40,7 +39,7 @@ public:
      *
      * @param routes the routes object
      */
- explicit request_handler(httpserver::routes* routes, const boost::program_options::variables_map& _config); + explicit request_handler(httpserver::routes* routes, std::map<std::string,std::vector<std::string>>& _config);

     request_handler(const request_handler&) = delete;

@@ -74,7 +73,7 @@ public:
 private:
     httpserver::routes* routes;
     std::vector<std::string> allowed_domains;
-    const boost::program_options::variables_map& config;
+    const std::map<std::string,std::vector<std::string>>& config;

 };

diff --git a/modules/httpserver-api/routes.hh b/modules/httpserver-api/routes.hh
--- a/modules/httpserver-api/routes.hh
+++ b/modules/httpserver-api/routes.hh
@@ -14,7 +14,6 @@
 #include "common.hh"
 #include "reply.hh"

-#include <boost/program_options/variables_map.hpp>
 #include <unordered_map>
 #include <vector>

diff --git a/modules/httpserver-api/server.cc b/modules/httpserver-api/server.cc
--- a/modules/httpserver-api/server.cc
+++ b/modules/httpserver-api/server.cc
@@ -17,6 +17,7 @@

 #include <utility>
 #include <openssl/ssl.h>
+#include <osv/options.hh>

 namespace http {

@@ -28,17 +29,17 @@ static bool exists(const std::string& path)
     return stat(path.c_str(), &s) == 0;
 }

-server::server(const boost::program_options::variables_map* config,
+server::server(std::map<std::string,std::vector<std::string>> &config,
                httpserver::routes* routes)
     : io_service_()
     , connection_manager_()
-    , request_handler_(routes, *config)
+    , request_handler_(routes, config)
 {
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
     boost::asio::ip::tcp::resolver resolver(io_service_);
     boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve({
-        (*config)["ipaddress"].as<std::string>(),
-        (*config)["port"].as<std::string>()
+        options::extract_option_value(config, "ipaddress"),
+        options::extract_option_value(config, "port")
     });

     tcp::acceptor tcp_acceptor(io_service_);
@@ -47,12 +48,22 @@ server::server(const boost::program_options::variables_map* config,
     tcp_acceptor.bind(endpoint);
     tcp_acceptor.listen();

-    if (config->count("ssl")) {
+ if (options::extract_option_flag(config, "ssl", [](const std::string &message) {
+            std::cerr << message << std::endl;
+            throw std::runtime_error("invalid configuration");
+        })) {
         ensure_openssl_initialized();

-        auto ca_cert_path = (*config)["cacert"].as<std::string>();
-        auto cert_path = (*config)["cert"].as<std::string>();
-        auto key_path = (*config)["key"].as<std::string>();
+        auto ca_cert_path = options::extract_option_value(config,"cacert");
+        auto cert_path = options::extract_option_value(config,"cert");
+        auto key_path = options::extract_option_value(config,"key");
+
+        if (!config.empty()) {
+            for (auto option : config) {
+ std::cout << "Unrecognized option: " << option.first << std::endl;
+            }
+            throw std::runtime_error("invalid configuration");
+        }

         bool valid = true;
         for (auto& path : {ca_cert_path, cert_path, key_path}) {
@@ -70,6 +81,13 @@ server::server(const boost::program_options::variables_map* config, ssl::context ctx = make_ssl_context(ca_cert_path, cert_path, key_path); acceptor_.reset(new ssl_acceptor(io_service_, std::move(ctx), std::move(tcp_acceptor)));
     } else {
+        if (!config.empty()) {
+            for (auto option : config) {
+ std::cout << "Unrecognized option: " << option.first << std::endl;
+            }
+            throw std::runtime_error("invalid configuration");
+        }
+
acceptor_.reset(new plain_acceptor(io_service_, std::move(tcp_acceptor)));
     }

diff --git a/modules/httpserver-api/server.hh b/modules/httpserver-api/server.hh
--- a/modules/httpserver-api/server.hh
+++ b/modules/httpserver-api/server.hh
@@ -17,7 +17,6 @@
 #include "connection.hh"
 #include "transport.hh"

-#include <boost/program_options/variables_map.hpp>
 #include <boost/asio.hpp>
 #include <string>
 #include <memory>
@@ -43,7 +42,7 @@ public:
      * @param config a configuration object
      * @param routes the routes object
      */
-    explicit server(const boost::program_options::variables_map* config,
+    explicit server(std::map<std::string,std::vector<std::string>> &config,
                     httpserver::routes* routes);

     server(const server&) = delete;

--
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/000000000000151f020593fdd958%40google.com.

Reply via email to