aboutsummaryrefslogtreecommitdiff
path: root/brep
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-04-30 14:25:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-04-30 14:25:29 +0200
commit07780b06aa7b0fe049cc412309cf87e7fb10a0ef (patch)
treeb6d0f1ee50223f5cbbc4b8c5d0dc4f69ff7f2352 /brep
parent259a92ac4e1ac50e4c029f54265b735f6214b49d (diff)
Implement module configuration with an option list
Diffstat (limited to 'brep')
-rw-r--r--brep/module24
-rw-r--r--brep/module.cxx68
-rw-r--r--brep/options.cli24
-rw-r--r--brep/search10
-rw-r--r--brep/search.cxx37
-rw-r--r--brep/view10
-rw-r--r--brep/view.cxx31
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>";
}
}
diff --git a/brep/view b/brep/view
index 819eff3..d97f9cf 100644
--- a/brep/view
+++ b/brep/view
@@ -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>";
}
}