diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-04-30 14:25:29 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-04-30 14:25:29 +0200 |
commit | 07780b06aa7b0fe049cc412309cf87e7fb10a0ef (patch) | |
tree | b6d0f1ee50223f5cbbc4b8c5d0dc4f69ff7f2352 /brep | |
parent | 259a92ac4e1ac50e4c029f54265b735f6214b49d (diff) |
Implement module configuration with an option list
Diffstat (limited to 'brep')
-rw-r--r-- | brep/module | 24 | ||||
-rw-r--r-- | brep/module.cxx | 68 | ||||
-rw-r--r-- | brep/options.cli | 24 | ||||
-rw-r--r-- | brep/search | 10 | ||||
-rw-r--r-- | brep/search.cxx | 37 | ||||
-rw-r--r-- | brep/view | 10 | ||||
-rw-r--r-- | brep/view.cxx | 31 |
7 files changed, 187 insertions, 17 deletions
diff --git a/brep/module b/brep/module index 54d41cf..d1399fb 100644 --- a/brep/module +++ b/brep/module @@ -11,6 +11,7 @@ #include <web/module> +#include <brep/options> #include <brep/diagnostics> namespace brep @@ -69,10 +70,6 @@ namespace brep // class module: public web::module { - public: - virtual void - handle (request&, response&) = 0; - // Diagnostics. // protected: @@ -95,18 +92,33 @@ namespace brep module (); module (const module& ); + private: virtual void handle (request&, response&, log&); virtual void - init (const char* path); + handle (request&, response&) = 0; + + virtual void + init (const name_values&, log&); + + // Can be overriden by module implementation which has configuration + // options. + // + virtual void + init (::cli::scanner& s) + { + // Just scan options to ensure there is no misspelled ones. + // + module_options o (s, cli::unknown_mode::fail, cli::unknown_mode::fail); + } // Diagnostics implementation details. // private: log* log_ {nullptr}; // Diagnostics backend provided by the web server. - public: + private: // Extract function name from a __PRETTY_FUNCTION__. // Throw std::invalid_argument if fail to parse. // diff --git a/brep/module.cxx b/brep/module.cxx index a803386..44154d6 100644 --- a/brep/module.cxx +++ b/brep/module.cxx @@ -7,6 +7,7 @@ #include <httpd/httpd.h> #include <httpd/http_log.h> +#include <memory> // unique_ptr #include <string> #include <cstring> // strncmp() #include <stdexcept> @@ -15,6 +16,8 @@ #include <web/module> #include <web/apache/log> +#include <brep/options> + using namespace std; using namespace placeholders; // For std::bind's _1, etc. @@ -52,10 +55,8 @@ namespace brep name = d.name; } - o << name << ": " << sev_str[d.sev] << ": " << d.msg << endl; - - //o << "[" << s[static_cast<int> (d.sev)] << "] [" - // << name << "] " << d.msg << std::endl; + o << name << ": " << sev_str[static_cast<size_t> (d.sev)] << ": " + << d.msg << endl; } } catch (const sequence_error&) @@ -67,9 +68,64 @@ namespace brep } } + // Parse options with a cli-generated scanner. Options verb and conf are + // recognized by brep::module::init while others to be interpreted by the + // derived class init method. If there is an option which can not be + // interpreted not by brep::module::init nor by derived class init method + // then web server is terminated with a corresponding error message being + // logged. + // void module:: - init (const char* path) + init (const name_values& options, log& log) { + log_ = &log; + + int argc = 0; + std::unique_ptr<const char*[]> argv (new const char*[options.size () * 2]); + + for (const auto& nv: options) + { + argv[argc++] = nv.name.c_str (); + argv[argc++] = nv.value.c_str (); + } + + try + { + { + // Read module implementation configuration. + // + cli::argv_file_scanner s (0, + argc, + const_cast<char**> (argv.get ()), + "conf"); + + init (s); + } + + // Read brep::module configuration. + // + cli::argv_file_scanner s (0, + argc, + const_cast<char**> (argv.get ()), + "conf"); + + module_options o (s, + ::cli::unknown_mode::skip, + ::cli::unknown_mode::skip); + + verb_ = o.verb (); + } + catch (const server_error& e) + { + log_write (e.data); + throw runtime_error ("initialization failed"); + } + catch (const cli::exception& e) + { + std::ostringstream o; + e.print (o); + throw runtime_error (o.str ()); + } } module:: @@ -166,7 +222,7 @@ namespace brep al->write (e.loc.file.c_str (), e.loc.line, name.c_str (), - s[static_cast<int> (e.sev)], + s[static_cast<size_t> (e.sev)], e.msg.c_str ()); } } diff --git a/brep/options.cli b/brep/options.cli new file mode 100644 index 0000000..cbd5d3a --- /dev/null +++ b/brep/options.cli @@ -0,0 +1,24 @@ +include <string>; + +namespace brep +{ + class module_options + { + unsigned int verb = 0; + }; + + class db_options + { + std::string db-host = "localhost"; + unsigned short db-port = 3306; + }; + + class search_options: module_options, db_options + { + unsigned int results-on-page = 10; + }; + + class view_options: module_options, db_options + { + }; +} diff --git a/brep/search b/brep/search index 9ea9345..a4edf01 100644 --- a/brep/search +++ b/brep/search @@ -5,7 +5,10 @@ #ifndef BREP_SEARCH #define BREP_SEARCH +#include <memory> // shared_ptr + #include <brep/module> +#include <brep/options> namespace brep { @@ -14,6 +17,13 @@ namespace brep public: virtual void handle (request&, response&); + + virtual void + init (::cli::scanner&); + + private: + + std::shared_ptr<search_options> options_; }; } diff --git a/brep/search.cxx b/brep/search.cxx index 9e6ab4b..15811e3 100644 --- a/brep/search.cxx +++ b/brep/search.cxx @@ -4,6 +4,7 @@ #include <brep/search> +#include <memory> // shared_ptr, make_shared() #include <chrono> #include <ostream> @@ -14,6 +15,23 @@ using namespace std; namespace brep { void search:: + init (::cli::scanner& s) + { + MODULE_DIAG; + + options_ = std::make_shared<search_options> (s, + ::cli::unknown_mode::fail, + ::cli::unknown_mode::fail); + + if (options_->results_on_page () > 30) + fail << "too many search results on page: " + << options_->results_on_page (); + else if (options_->results_on_page () > 10) + warn << options_->results_on_page () + << " search results on page is quite a lot but will try to cope"; + } + + void search:: handle (request& rq, response& rs) { MODULE_DIAG; @@ -24,9 +42,17 @@ namespace brep info << "handling search request from "; // << rq.client_ip (); - ostream& o (rs.content (200, "text/html;charset=utf-8", true)); + ostream& o (rs.content ()); + + o << "<html><head></head><body>"; + + o << "<b>Options:</b>" + << "<br>\ntracing verbosity: " << options_->verb () + << "<br>\ndb endpoint: " << options_->db_host () << ":" + << options_->db_port () + << "<br>\nsearch results on page: " << options_->results_on_page (); - o << "<html><head></head><body><b>Params:</b>"; + o << "<p>\n<b>Params:</b>"; const name_values& ps (rq.parameters ()); @@ -44,13 +70,14 @@ namespace brep o << "<br>\n" << p.name << "=" << p.value; } - o << "<br>\n<b>Cookies:</b>"; + o << "<p>\n<b>Cookies:</b>"; for (const auto& c: rq.cookies ()) { - o << "<br>\n" << c.name << "=" << c.value << " "; + o << "<br>\n" << c.name << "=" << c.value; } - o << "</body></html>"; + o << "<p><a href='view'>View</a>" + << "</body></html>"; } } @@ -5,7 +5,10 @@ #ifndef BREP_VIEW #define BREP_VIEW +#include <memory> // shared_ptr + #include <brep/module> +#include <brep/options> namespace brep { @@ -14,6 +17,13 @@ namespace brep public: virtual void handle (request&, response&); + + virtual void + init (::cli::scanner&); + + private: + + std::shared_ptr<view_options> options_; }; } diff --git a/brep/view.cxx b/brep/view.cxx index 6dafa1b..7ccc159 100644 --- a/brep/view.cxx +++ b/brep/view.cxx @@ -4,12 +4,43 @@ #include <brep/view> +#include <memory> // shared_ptr, make_shared() +#include <ostream> + +#include <web/module> + using namespace std; namespace brep { void view:: + init (::cli::scanner& s) + { + options_ = std::make_shared<view_options> (s, + ::cli::unknown_mode::fail, + ::cli::unknown_mode::fail); + } + + void view:: handle (request& rq, response& rs) { + ostream& o (rs.content (200, "text/html;charset=utf-8", false)); + + o << "<html><head></head><body>"; + + o << "<b>Options:</b>" + << "<br>\ntracing verbosity: " << options_->verb () + << "<br>\ndb endpoint: " << options_->db_host () << ":" + << options_->db_port (); + + o << "<p>\n<b>Cookies:</b>"; + + for (const auto& c: rq.cookies ()) + { + o << "<br>\n" << c.name << "=" << c.value; + } + + o << "<p><a href='search?a=1&b&c=2&d=&&x=a+b'>Search</a>" + << "</body></html>"; } } |