aboutsummaryrefslogtreecommitdiff
path: root/brep
diff options
context:
space:
mode:
Diffstat (limited to 'brep')
-rw-r--r--brep/buildfile22
-rw-r--r--brep/module63
-rw-r--r--brep/module.cxx167
-rw-r--r--brep/options.cli38
-rw-r--r--brep/package-details9
-rw-r--r--brep/package-details.cxx23
-rw-r--r--brep/package-search9
-rw-r--r--brep/package-search.cxx21
-rw-r--r--brep/package-version-details12
-rw-r--r--brep/package-version-details.cxx22
-rw-r--r--brep/package.cxx1
-rw-r--r--brep/page1
-rw-r--r--brep/page.cxx1
-rw-r--r--brep/repository-details9
-rw-r--r--brep/repository-details.cxx17
-rw-r--r--brep/repository-root29
-rw-r--r--brep/repository-root.cxx183
-rw-r--r--brep/services.cxx38
-rw-r--r--brep/shared-database.cxx7
-rw-r--r--brep/types-parsers1
-rw-r--r--brep/types-parsers.cxx1
21 files changed, 450 insertions, 224 deletions
diff --git a/brep/buildfile b/brep/buildfile
index b879b2d..0369098 100644
--- a/brep/buildfile
+++ b/brep/buildfile
@@ -4,7 +4,10 @@
using cli
-.: libso{brep brep-apache}
+# @@ The target should actually be mod_brep.so, not libmod_brep.so. Such
+# customization is not supported yet.
+#
+.: libso{brep mod_brep}
# brep library build rules.
#
@@ -17,25 +20,26 @@ brep = cxx{package package-traits package-odb}
libso{brep}: $brep $libs
libso{brep}: cxx.export.poptions = -I$out_root -I$src_root
-# brep-apache library build rules.
+# mod_brep library build rules.
#
import libs += libstudxml%lib{studxml}
-brep = cxx{diagnostics module services repository-root package-search \
- package-details package-version-details repository-details \
- shared-database page types-parsers} \
+brep = cxx{services diagnostics module repository-root package-search \
+ package-details package-version-details repository-details \
+ shared-database page types-parsers} \
cli.cxx{options}
web = ../web/apache/cxx{request service} ../web/cxx{mime-url-encoding}
-libso{brep-apache}: $brep $web libso{brep} $libs
+libso{mod_brep}: $brep $web libso{brep} $libs
# Set option prefix to the empty value to handle all unknown request parameters
# uniformly with a single catch block.
#
-cli.options += -I $src_root --include-with-brackets --include-prefix brep \
---guard-prefix BREP --cxx-prologue "#include <brep/types-parsers>" \
+cli.options += --std c++11 -I $src_root --include-with-brackets \
+--include-prefix brep --guard-prefix BREP \
+--cxx-prologue "#include <brep/types-parsers>" \
--cli-namespace brep::cli --generate-file-scanner --suppress-usage \
---option-prefix ""
+--generate-modifier --generate-description --option-prefix ""
cli.cxx{options}: cli{options}
diff --git a/brep/module b/brep/module
index 295744d..4ac6023 100644
--- a/brep/module
+++ b/brep/module
@@ -9,6 +9,7 @@
#include <brep/types>
#include <brep/utility>
+
#include <brep/options>
#include <brep/diagnostics>
@@ -23,6 +24,7 @@ namespace brep
using web::status_code;
using web::invalid_request;
using web::sequence_error;
+ using web::option_descriptions;
using web::name_value;
using web::name_values;
using web::request;
@@ -94,12 +96,24 @@ namespace brep
module ();
module (const module& );
+ static name_values
+ filter (const name_values&, const option_descriptions&);
+
+ static option_descriptions
+ convert (const cli::options&);
+
+ static void
+ append (option_descriptions& dst, const cli::options& src);
+
+ static void
+ append (option_descriptions& dst, const option_descriptions& src);
+
// Can be used by module implementation to parse HTTP request parameters.
//
- class param_scanner: public cli::scanner
+ class name_value_scanner: public cli::scanner
{
public:
- param_scanner (const name_values&) noexcept;
+ name_value_scanner (const name_values&) noexcept;
virtual bool
more ();
@@ -120,36 +134,43 @@ namespace brep
};
public:
- // Can be called normally by the web server or our custom request
- // dispatching mechanism.
- //
- virtual void
- handle (request&, response&) = 0;
+ virtual const cli::options&
+ cli_options () const = 0;
- bool
- loaded () const noexcept {return loaded_;}
+ virtual void
+ init (cli::scanner&) = 0;
- private:
+ // Can be overriden by custom request dispatcher to initialize sub-modules.
+ //
virtual void
- handle (request&, response&, log&);
+ init (const name_values&);
virtual void
init (const name_values&, log&);
- // Can be overriden by module implementation which has configuration
- // options.
+ virtual bool
+ handle (request&, response&) = 0;
+
+ // web::module interface.
//
- virtual void
- init (cli::scanner& s)
- {
- // Just scan options to ensure there is no misspelled ones.
- //
- options::module o (s, cli::unknown_mode::fail, cli::unknown_mode::fail);
- }
+ public:
+ // Custom request dispatcher can aggregate its own option descriptions with
+ // sub-modules option descriptions. In this case it should still call the
+ // base implementation in order to include the brep::module's options.
+ //
+ virtual option_descriptions
+ options ();
+
+ private:
+ virtual bool
+ handle (request&, response&, log&);
+
+ name_values
+ expand_options (const name_values&);
// Diagnostics implementation details.
//
- private:
+ protected:
log* log_ {nullptr}; // Diagnostics backend provided by the web server.
private:
diff --git a/brep/module.cxx b/brep/module.cxx
index 68177b1..253d807 100644
--- a/brep/module.cxx
+++ b/brep/module.cxx
@@ -18,6 +18,7 @@
#include <brep/types>
#include <brep/utility>
+
#include <brep/options>
using namespace std;
@@ -29,7 +30,7 @@ namespace brep
// module
//
- void module::
+ bool module::
handle (request& rq, response& rs, log& l)
{
assert (loaded_);
@@ -38,7 +39,7 @@ namespace brep
try
{
- handle (rq, rs);
+ return handle (rq, rs);
}
catch (const server_error& e)
{
@@ -74,24 +75,77 @@ namespace brep
// it.
}
}
+
+ return true;
+ }
+
+ option_descriptions module::
+ convert (const cli::options& o)
+ {
+ option_descriptions r;
+ append (r, o);
+ return r;
}
- // 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 name_values& options, log& log)
+ append (option_descriptions& dst, const cli::options& src)
{
- assert (!loaded_);
+ for (const auto& o: src)
+ {
+ bool v (!o.flag ());
+ auto i (dst.emplace (o.name (), v));
+ assert (i.first->second == v); // Consistent option/flag.
- log_ = &log;
- vector<const char*> argv;
+ for (const auto& a: o.aliases ())
+ {
+ i = dst.emplace (a, v);
+ assert (i.first->second == v);
+ }
+ }
+ }
+
+ void module::
+ append (option_descriptions& dst, const option_descriptions& src)
+ {
+ for (const auto& o: src)
+ {
+ auto i (dst.emplace (o));
+ assert (i.first->second == o.second); // Consistent option/flag.
+ }
+ }
+
+ name_values module::
+ filter (const name_values& v, const option_descriptions& d)
+ {
+ name_values r;
+ for (const auto& nv: v)
+ {
+ if (d.find (nv.name) != d.end ())
+ r.push_back (nv);
+ }
+
+ return r;
+ }
+
+ // Convert CLI option descriptions to the general interface of option
+ // descriptions, extend with brep::module own option descriptions.
+ //
+ option_descriptions module::
+ options ()
+ {
+ option_descriptions r ({{"conf", true}});
+ append (r, options::module::description ());
+ append (r, cli_options ());
+ return r;
+ }
- for (const auto& nv: options)
+ // Expand option list parsing configuration files.
+ //
+ name_values module::
+ expand_options (const name_values& v)
+ {
+ vector<const char*> argv;
+ for (const auto& nv: v)
{
argv.push_back (nv.name.c_str ());
@@ -100,29 +154,60 @@ namespace brep
}
int argc (argv.size ());
+ argv_file_scanner s (0, argc, const_cast<char**> (argv.data ()), "conf");
+
+ name_values r;
+ const option_descriptions& o (options ());
+
+ while (s.more ())
+ {
+ string n (s.next ());
+ auto i (o.find (n));
+
+ if (i == o.end ())
+ throw unknown_argument (n);
+
+ optional<string> v;
+ if (i->second)
+ v = s.next ();
+
+ r.emplace_back (move (n), move (v));
+ }
+
+ return r;
+ }
+
+ // 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 init(). If there is an option which can not be interpreted
+ // neither by brep::module nor by the derived class, then the web server
+ // is terminated with a corresponding error message being logged. Though
+ // this should not happen if the options() function returned the correct
+ // set of options.
+ //
+ void module::
+ init (const name_values& options, log& log)
+ {
+ assert (!loaded_);
+
+ log_ = &log;
try
{
- {
- // Read module implementation configuration.
- //
- argv_file_scanner s (0,
- argc,
- const_cast<char**> (argv.data ()),
- "conf");
+ name_values opts (expand_options (options));
- init (s);
- }
+ // Read module implementation configuration.
+ //
+ init (opts);
// Read brep::module configuration.
//
- argv_file_scanner s (0,
- argc,
- const_cast<char**> (argv.data ()),
- "conf");
+ static option_descriptions od (convert (options::module::description ()));
+ name_values mo (filter (opts, od));
+ name_value_scanner s (mo);
+ options::module o (s, unknown_mode::fail, unknown_mode::fail);
- options::module o (s, unknown_mode::skip, unknown_mode::skip);
- verb_ = o.verb ();
+ verb_ = o.log_verbosity ();
loaded_ = true;
}
catch (const server_error& e)
@@ -138,6 +223,14 @@ namespace brep
}
}
+ void module::
+ init (const name_values& options)
+ {
+ name_value_scanner s (options);
+ init (s);
+ assert (!s.more ()); // Module didn't handle its options.
+ }
+
module::
module (): log_writer_ (bind (&module::log_write, this, _1)) {}
@@ -208,7 +301,7 @@ namespace brep
//@@ Cast log_ to apache::log and write the records.
//
- auto al (dynamic_cast<::web::apache::log*> (log_));
+ auto al (dynamic_cast<web::apache::log*> (log_));
if (al)
{
@@ -240,23 +333,23 @@ namespace brep
}
}
- // module::param_scanner
+ // module::name_value_scanner
//
- module::param_scanner::
- param_scanner (const name_values& nv) noexcept
+ module::name_value_scanner::
+ name_value_scanner (const name_values& nv) noexcept
: name_values_ (nv),
i_ (nv.begin ()),
name_ (true)
{
}
- bool module::param_scanner::
+ bool module::name_value_scanner::
more ()
{
return i_ != name_values_.end ();
}
- const char* module::param_scanner::
+ const char* module::name_value_scanner::
peek ()
{
if (i_ != name_values_.end ())
@@ -265,7 +358,7 @@ namespace brep
throw eos_reached ();
}
- const char* module::param_scanner::
+ const char* module::name_value_scanner::
next ()
{
if (i_ != name_values_.end ())
@@ -278,7 +371,7 @@ namespace brep
throw eos_reached ();
}
- void module::param_scanner::
+ void module::name_value_scanner::
skip ()
{
if (i_ != name_values_.end ())
diff --git a/brep/options.cli b/brep/options.cli
index fa05b56..d5041c8 100644
--- a/brep/options.cli
+++ b/brep/options.cli
@@ -3,6 +3,7 @@
// license : MIT; see accompanying LICENSE file
include <brep/types>;
+
include <brep/options-types>;
namespace brep
@@ -11,10 +12,12 @@ namespace brep
//
namespace options
{
+ // Option groups.
+ //
class module
{
- uint16_t verb;
- dir_path root;
+ uint16_t log-verbosity;
+ dir_path root = "/";
};
class db
@@ -23,28 +26,39 @@ namespace brep
uint16_t db-port = 5432;
};
- class package_search: module, db
+ class search
+ {
+ uint16_t search-results = 10;
+ uint16_t pager-pages = 5;
+ };
+
+ class package
+ {
+ uint16_t description-len = 500; // ~ 80 chars x 6 lines.
+ uint16_t changes-len = 5000; // ~ 80 chars x 60 lines.
+ };
+
+ // Module options.
+ //
+ class package_search: module, db, search
{
- uint16_t results-on-page = 10;
- uint16_t pages-in-pager = 5;
};
- class package_details: module, db
+ class package_details: module, db, search, package
{
- uint16_t results-on-page = 10;
- uint16_t pages-in-pager = 5;
- uint16_t description-length = 500; // ~ 80 chars x 6 lines.
};
- class package_version_details: module, db
+ class package_version_details: module, db, package
{
- uint16_t description-length = 500; // ~ 80 chars x 6 lines.
- uint16_t changes-length = 5000; // ~ 80 chars x 60 lines.
};
class repository_details: module, db
{
};
+
+ class repository_root: module
+ {
+ };
}
// Web module HTTP request parameters.
diff --git a/brep/package-details b/brep/package-details
index 214a0fe..6766797 100644
--- a/brep/package-details
+++ b/brep/package-details
@@ -8,6 +8,7 @@
#include <odb/forward.hxx> // database
#include <brep/types>
+
#include <brep/module>
#include <brep/options>
@@ -15,10 +16,14 @@ namespace brep
{
class package_details: public module
{
- private:
- virtual void
+ public:
+ virtual bool
handle (request&, response&);
+ virtual const cli::options&
+ cli_options () const {return options::package_details::description ();}
+
+ private:
virtual void
init (cli::scanner&);
diff --git a/brep/package-details.cxx b/brep/package-details.cxx
index 4b99feb..30e185e 100644
--- a/brep/package-details.cxx
+++ b/brep/package-details.cxx
@@ -14,9 +14,10 @@
#include <web/module>
#include <web/mime-url-encoding>
-#include <brep/page>
#include <brep/types>
#include <brep/utility>
+
+#include <brep/page>
#include <brep/options>
#include <brep/package>
#include <brep/package-odb>
@@ -33,6 +34,9 @@ init (scanner& s)
options_ = make_shared<options::package_details> (
s, unknown_mode::fail, unknown_mode::fail);
+ if (options_->root ().empty ())
+ options_->root (dir_path ("/"));
+
db_ = shared_database (options_->db_host (), options_->db_port ());
}
@@ -51,7 +55,7 @@ search_params (const brep::string& n, const brep::string& q)
")";
}
-void brep::package_details::
+bool brep::package_details::
handle (request& rq, response& rs)
{
using namespace web;
@@ -62,11 +66,8 @@ handle (request& rq, response& rs)
// The module options object is not changed after being created once per
// server process.
//
- static const size_t res_page (options_->results_on_page ());
- static const dir_path& root (
- options_->root ().empty ()
- ? dir_path ("/")
- : options_->root ());
+ static const size_t res_page (options_->search_results ());
+ static const dir_path& root (options_->root ());
const string& name (*rq.path ().rbegin ());
const string ename (mime_url_encode (name));
@@ -76,7 +77,7 @@ handle (request& rq, response& rs)
try
{
- param_scanner s (rq.parameters ());
+ name_value_scanner s (rq.parameters ());
params = params::package_details (
s, unknown_mode::fail, unknown_mode::fail);
@@ -159,7 +160,7 @@ handle (request& rq, response& rs)
if (const auto& d = pkg->description)
s << (full
? P_DESCRIPTION (*d, id)
- : P_DESCRIPTION (*d, options_->description_length (),
+ : P_DESCRIPTION (*d, options_->description_len (),
url (!full, squery, page, id)));
s << TABLE(CLASS="proplist", ID="package")
@@ -231,9 +232,11 @@ handle (request& rq, response& rs)
t.commit ();
- s << DIV_PAGER (page, pkg_count, res_page, options_->pages_in_pager (),
+ s << DIV_PAGER (page, pkg_count, res_page, options_->pager_pages (),
url (full, squery))
<< ~DIV
<< ~BODY
<< ~HTML;
+
+ return true;
}
diff --git a/brep/package-search b/brep/package-search
index a5c441e..63ec6e0 100644
--- a/brep/package-search
+++ b/brep/package-search
@@ -8,6 +8,7 @@
#include <odb/forward.hxx> // database
#include <brep/types>
+
#include <brep/module>
#include <brep/options>
@@ -15,10 +16,14 @@ namespace brep
{
class package_search: public module
{
- private:
- virtual void
+ public:
+ virtual bool
handle (request&, response&);
+ virtual const cli::options&
+ cli_options () const {return options::package_search::description ();}
+
+ private:
virtual void
init (cli::scanner&);
diff --git a/brep/package-search.cxx b/brep/package-search.cxx
index f2f922c..62b162b 100644
--- a/brep/package-search.cxx
+++ b/brep/package-search.cxx
@@ -14,9 +14,10 @@
#include <web/module>
#include <web/mime-url-encoding>
-#include <brep/page>
#include <brep/types>
#include <brep/utility>
+
+#include <brep/page>
#include <brep/options>
#include <brep/package>
#include <brep/package-odb>
@@ -33,6 +34,9 @@ init (scanner& s)
options_ = make_shared<options::package_search> (
s, unknown_mode::fail, unknown_mode::fail);
+ if (options_->root ().empty ())
+ options_->root (dir_path ("/"));
+
db_ = shared_database (options_->db_host (), options_->db_port ());
}
@@ -48,7 +52,7 @@ search_param (const brep::string& q)
")";
}
-void brep::package_search::
+bool brep::package_search::
handle (request& rq, response& rs)
{
using namespace web::xhtml;
@@ -58,17 +62,14 @@ handle (request& rq, response& rs)
// The module options object is not changed after being created once per
// server process.
//
- static const size_t res_page (options_->results_on_page ());
- static const dir_path& root (
- options_->root ().empty ()
- ? dir_path ("/")
- : options_->root ());
+ static const size_t res_page (options_->search_results ());
+ static const dir_path& root (options_->root ());
params::package_search params;
try
{
- param_scanner s (rq.parameters ());
+ name_value_scanner s (rq.parameters ());
params = params::package_search (s, unknown_mode::fail, unknown_mode::fail);
}
catch (const unknown_argument& e)
@@ -137,9 +138,11 @@ handle (request& rq, response& rs)
t.commit ();
- s << DIV_PAGER (page, pkg_count, res_page, options_->pages_in_pager (),
+ s << DIV_PAGER (page, pkg_count, res_page, options_->pager_pages (),
root.string () + squery_param)
<< ~DIV
<< ~BODY
<< ~HTML;
+
+ return true;
}
diff --git a/brep/package-version-details b/brep/package-version-details
index 36b7420..8057097 100644
--- a/brep/package-version-details
+++ b/brep/package-version-details
@@ -8,6 +8,7 @@
#include <odb/forward.hxx> // database
#include <brep/types>
+
#include <brep/module>
#include <brep/options>
@@ -15,10 +16,17 @@ namespace brep
{
class package_version_details: public module
{
- private:
- virtual void
+ public:
+ virtual bool
handle (request&, response&);
+ virtual const cli::options&
+ cli_options () const
+ {
+ return options::package_version_details::description ();
+ }
+
+ private:
virtual void
init (cli::scanner&);
diff --git a/brep/package-version-details.cxx b/brep/package-version-details.cxx
index a0ad7d4..8f6cd7d 100644
--- a/brep/package-version-details.cxx
+++ b/brep/package-version-details.cxx
@@ -16,9 +16,10 @@
#include <web/module>
#include <web/mime-url-encoding>
-#include <brep/page>
#include <brep/types>
#include <brep/utility>
+
+#include <brep/page>
#include <brep/options>
#include <brep/package>
#include <brep/package-odb>
@@ -36,10 +37,13 @@ init (scanner& s)
options_ = make_shared<options::package_version_details> (
s, unknown_mode::fail, unknown_mode::fail);
+ if (options_->root ().empty ())
+ options_->root (dir_path ("/"));
+
db_ = shared_database (options_->db_host (), options_->db_port ());
}
-void brep::package_version_details::
+bool brep::package_version_details::
handle (request& rq, response& rs)
{
using namespace web;
@@ -50,10 +54,7 @@ handle (request& rq, response& rs)
// The module options object is not changed after being created once per
// server process.
//
- static const dir_path& root (
- options_->root ().empty ()
- ? dir_path ("/")
- : options_->root ());
+ static const dir_path& root (options_->root ());
auto i (rq.path ().rbegin ());
version ver;
@@ -77,7 +78,7 @@ handle (request& rq, response& rs)
try
{
- param_scanner s (rq.parameters ());
+ name_value_scanner s (rq.parameters ());
params = params::package_version_details (
s, unknown_mode::fail, unknown_mode::fail);
@@ -151,7 +152,7 @@ handle (request& rq, response& rs)
if (const auto& d = pkg->description)
s << (full
? P_DESCRIPTION (*d, id)
- : P_DESCRIPTION (*d, options_->description_length (),
+ : P_DESCRIPTION (*d, options_->description_len (),
url (!full, id)));
assert (pkg->location);
@@ -301,10 +302,11 @@ handle (request& rq, response& rs)
s << H3 << "Changes" << ~H3
<< (full
? PRE_CHANGES (ch)
- : PRE_CHANGES (ch, options_->description_length (),
- url (!full, "changes")));
+ : PRE_CHANGES (ch, options_->changes_len (), url (!full, "changes")));
s << ~DIV
<< ~BODY
<< ~HTML;
+
+ return true;
}
diff --git a/brep/package.cxx b/brep/package.cxx
index ecaa369..c221fe8 100644
--- a/brep/package.cxx
+++ b/brep/package.cxx
@@ -10,6 +10,7 @@
#include <brep/types>
#include <brep/utility>
+
#include <brep/package-odb>
using namespace std;
diff --git a/brep/page b/brep/page
index 907bc45..9868984 100644
--- a/brep/page
+++ b/brep/page
@@ -8,6 +8,7 @@
#include <xml/forward>
#include <brep/types>
+
#include <brep/package>
namespace brep
diff --git a/brep/page.cxx b/brep/page.cxx
index 780d759..638a72b 100644
--- a/brep/page.cxx
+++ b/brep/page.cxx
@@ -17,6 +17,7 @@
#include <brep/types>
#include <brep/utility>
+
#include <brep/package>
#include <brep/package-odb>
diff --git a/brep/repository-details b/brep/repository-details
index fb41e32..7efc6a6 100644
--- a/brep/repository-details
+++ b/brep/repository-details
@@ -8,6 +8,7 @@
#include <odb/forward.hxx> // database
#include <brep/types>
+
#include <brep/module>
#include <brep/options>
@@ -15,10 +16,14 @@ namespace brep
{
class repository_details: public module
{
- private:
- virtual void
+ public:
+ virtual bool
handle (request&, response&);
+ virtual const cli::options&
+ cli_options () const {return options::repository_details::description ();}
+
+ private:
virtual void
init (cli::scanner&);
diff --git a/brep/repository-details.cxx b/brep/repository-details.cxx
index eb2885c..ee34dc2 100644
--- a/brep/repository-details.cxx
+++ b/brep/repository-details.cxx
@@ -13,9 +13,10 @@
#include <web/module>
#include <web/mime-url-encoding>
-#include <brep/page>
#include <brep/types>
#include <brep/utility>
+
+#include <brep/page>
#include <brep/options>
#include <brep/package>
#include <brep/package-odb>
@@ -32,10 +33,13 @@ init (scanner& s)
options_ = make_shared<options::repository_details> (
s, unknown_mode::fail, unknown_mode::fail);
+ if (options_->root ().empty ())
+ options_->root (dir_path ("/"));
+
db_ = shared_database (options_->db_host (), options_->db_port ());
}
-void brep::repository_details::
+bool brep::repository_details::
handle (request& rq, response& rs)
{
using namespace web::xhtml;
@@ -45,16 +49,13 @@ handle (request& rq, response& rs)
// The module options object is not changed after being created once per
// server process.
//
- static const dir_path& root (
- options_->root ().empty ()
- ? dir_path ("/")
- : options_->root ());
+ static const dir_path& root (options_->root ());
// Make sure no parameters passed.
//
try
{
- param_scanner s (rq.parameters ());
+ name_value_scanner s (rq.parameters ());
params::repository_details (s, unknown_mode::fail, unknown_mode::fail);
}
catch (const unknown_argument& e)
@@ -106,4 +107,6 @@ handle (request& rq, response& rs)
s << ~DIV
<< ~BODY
<< ~HTML;
+
+ return true;
}
diff --git a/brep/repository-root b/brep/repository-root
index e5fba78..2397764 100644
--- a/brep/repository-root
+++ b/brep/repository-root
@@ -5,26 +5,45 @@
#ifndef BREP_REPOSITORY_ROOT
#define BREP_REPOSITORY_ROOT
+#include <brep/types>
+
#include <brep/module>
+#include <brep/options>
namespace brep
{
class package_search;
+ class package_details;
+ class package_version_details;
class repository_details;
class repository_root: public module
{
public:
- repository_root (package_search& ps, repository_details& rd)
- : package_search_ (ps), repository_details_ (rd) {}
+ repository_root ();
private:
- virtual void
+ virtual bool
handle (request&, response&);
+ virtual const cli::options&
+ cli_options () const {return options::repository_root::description ();}
+
+ virtual option_descriptions
+ options ();
+
+ virtual void
+ init (const name_values&);
+
+ virtual void
+ init (cli::scanner&);
+
private:
- package_search& package_search_;
- repository_details& repository_details_;
+ shared_ptr<package_search> package_search_;
+ shared_ptr<package_details> package_details_;
+ shared_ptr<package_version_details> package_version_details_;
+ shared_ptr<repository_details> repository_details_;
+ shared_ptr<options::repository_root> options_;
};
}
diff --git a/brep/repository-root.cxx b/brep/repository-root.cxx
index 180d61f..7af76b2 100644
--- a/brep/repository-root.cxx
+++ b/brep/repository-root.cxx
@@ -4,17 +4,22 @@
#include <brep/repository-root>
-#include <map>
-#include <functional>
+#include <sstream>
#include <web/module>
#include <brep/types>
#include <brep/utility>
+
+#include <brep/module>
+#include <brep/options>
#include <brep/package-search>
+#include <brep/package-details>
#include <brep/repository-details>
+#include <brep/package-version-details>
using namespace std;
+using namespace brep::cli;
namespace brep
{
@@ -45,75 +50,141 @@ namespace brep
// repository_root
//
+ repository_root::
+ repository_root ()
+ : package_search_ (make_shared<package_search> ()),
+ package_details_ (make_shared<package_details> ()),
+ package_version_details_ (make_shared<package_version_details> ()),
+ repository_details_ (make_shared<repository_details> ())
+ {
+ }
+
+ // Return amalgamation of repository_root and all its sub-modules option
+ // descriptions.
+ //
+ option_descriptions repository_root::
+ options ()
+ {
+ option_descriptions r (module::options ());
+ append (r, package_search_->options ());
+ append (r, package_details_->options ());
+ append (r, package_version_details_->options ());
+ append (r, repository_details_->options ());
+ return r;
+ }
+
+ // Initialize sub-modules and parse own configuration options.
+ //
void repository_root::
- handle (request& rq, response& rs)
+ init (const name_values& v)
{
- MODULE_DIAG;
+ auto sub_init ([this, &v](module& m)
+ {
+ m.init (filter (v, m.options ()), *log_);
+ });
- // Dispatch request handling to the appropriate module depending on the
- // function name passed as a first HTTP request parameter. The parameter
- // should have no value specified. If no function name is passed,
- // the default handler is selected. Example: cppget.org/?about
+ // Initialize sub-modules.
//
+ sub_init (*package_search_);
+ sub_init (*package_details_);
+ sub_init (*package_version_details_);
+ sub_init (*repository_details_);
- string func;
- name_values params (rq.parameters ());
-
- // Obtain the function name.
+ // Parse own configuration options.
//
- if (!params.empty () && !params.front ().value)
- {
- func = move (params.front ().name);
+ module::init (
+ filter (v, convert (options::repository_root::description ())));
+ }
- // Cleanup not to confuse the selected handler with the unknown parameter.
- //
- params.erase (params.begin ());
- }
+ void repository_root::
+ init (scanner& s)
+ {
+ MODULE_DIAG;
- // To handle the request a new module instance is created as a copy of
- // the corresponsing exemplar.
- //
- using module_ptr = unique_ptr<module>;
+ options_ = make_shared<options::repository_root> (
+ s, unknown_mode::fail, unknown_mode::fail);
- // Function name to module factory map.
- //
- const map<string, function<module_ptr()>>
- handlers ({
- {
- "about",
- [this]() -> module_ptr
- {return module_ptr (new repository_details (repository_details_));}
- },
- {
- string (), // The default handler.
- [this]() -> module_ptr
- {return module_ptr (new package_search (package_search_));}
- }});
+ if (options_->root ().empty ())
+ options_->root (dir_path ("/"));
+ }
- // Find proper handler.
- //
- auto i (handlers.find (func));
- if (i == handlers.end ())
- throw invalid_request (400, "unknown function");
+ bool repository_root::
+ handle (request& rq, response& rs)
+ {
+ MODULE_DIAG;
- module_ptr m (i->second ());
- if (m->loaded ())
+ static const dir_path& root (options_->root ());
+
+ const path& rpath (rq.path ());
+ if (!rpath.sub (root))
+ return false;
+
+ const path& lpath (rpath.leaf (root));
+
+ // @@ An exception thrown by the selected module handle () function call
+ // will be attributed to the repository-root service while being logged.
+ // Could intercept exception handling to add some sub-module attribution,
+ // but let's not complicate the code for the time being.
+ //
+ if (lpath.empty ())
{
- // Delegate request handling.
- //
- // @@ An exception thrown by the handler will be attributed to the
- // repository-root service while being logged. Could intercept
- // exception handling to fix that, but let's not complicate the
- // code for the time being.
+ // Dispatch request handling to the repository_details or the
+ // package_search module depending on the function name passed as a
+ // first HTTP request parameter. The parameter should have no value
+ // specified. Example: cppget.org/?about
//
- //
- request_proxy rqp (rq, params);
- m->handle (rqp, rs);
+ const name_values& params (rq.parameters ());
+ if (!params.empty () && !params.front ().value)
+ {
+ if (params.front ().name == "about")
+ {
+ // Cleanup not to confuse the selected module with the unknown
+ // parameter.
+ //
+ name_values p (params);
+ p.erase (p.begin ());
+
+ request_proxy rp (rq, p);
+ repository_details m (*repository_details_);
+ return m.handle (rp, rs);
+ }
+
+ throw invalid_request (400, "unknown function");
+ }
+ else
+ {
+ package_search m (*package_search_);
+ return m.handle (rq, rs);
+ }
}
else
- // The module is not loaded, presumably being disabled in the web server
- // configuration file.
+ {
+ // Dispatch request handling to the package_details or the
+ // package_version_details module depending on the HTTP request URL path.
+ //
+ auto i (lpath.begin ());
+ assert (i != lpath.end ());
+
+ const string& n (*i++); // Package name.
+
+ // Check if this is a package name and not a brep static content files
+ // (CSS) directory name or a repository directory name.
//
- throw invalid_request (404, "handler not available");
+ if (n != "@" && n.find_first_not_of ("0123456789") != string::npos)
+ {
+ if (i == lpath.end ())
+ {
+ package_details m (*package_details_);
+ return m.handle (rq, rs);
+ }
+ else if (++i == lpath.end ())
+ {
+ package_version_details m (*package_version_details_);
+ return m.handle (rq, rs);
+ }
+ }
+ }
+
+ return false;
}
}
diff --git a/brep/services.cxx b/brep/services.cxx
index b214a09..dcac22c 100644
--- a/brep/services.cxx
+++ b/brep/services.cxx
@@ -6,41 +6,7 @@
#include <web/apache/service>
-#include <brep/package-search>
-#include <brep/package-details>
#include <brep/repository-root>
-#include <brep/repository-details>
-#include <brep/package-version-details>
-using namespace brep;
-using web::apache::service;
-
-static package_search package_search_mod;
-service AP_MODULE_DECLARE_DATA package_search_srv (
- "package-search",
- package_search_mod,
- {"root", "db-host", "db-port", "conf"});
-
-static package_details package_details_mod;
-service AP_MODULE_DECLARE_DATA package_details_srv (
- "package-details",
- package_details_mod,
- {"root", "db-host", "db-port", "conf"});
-
-static package_version_details package_version_details_mod;
-service AP_MODULE_DECLARE_DATA package_version_details_srv (
- "package-version-details",
- package_version_details_mod,
- {"root", "db-host", "db-port", "conf"});
-
-static repository_details repository_details_mod;
-service AP_MODULE_DECLARE_DATA repository_details_srv (
- "repository-details",
- repository_details_mod,
- {"root", "db-host", "db-port", "conf"});
-
-static repository_root repository_root_mod (
- package_search_mod, repository_details_mod);
-service AP_MODULE_DECLARE_DATA repository_root_srv (
- "repository-root",
- repository_root_mod);
+static brep::repository_root mod;
+web::apache::service AP_MODULE_DECLARE_DATA brep_module ("brep", mod);
diff --git a/brep/shared-database.cxx b/brep/shared-database.cxx
index c1d128f..db6b811 100644
--- a/brep/shared-database.cxx
+++ b/brep/shared-database.cxx
@@ -19,10 +19,9 @@ namespace brep
using odb::pgsql::database;
static weak_ptr<database> db;
- // In C++11, function-static variable initialization is
- // guaranteed to be thread-safe, thought this doesn't
- // seem to be enough in our case (because we are re-
- // initializing the weak pointer).
+ // In C++11, function-static variable initialization is guaranteed to be
+ // thread-safe, thought this doesn't seem to be enough in our case
+ // (because we are re-initializing the weak pointer).
//
if (shared_ptr<database> d = db.lock ())
{
diff --git a/brep/types-parsers b/brep/types-parsers
index dfe86a6..3165518 100644
--- a/brep/types-parsers
+++ b/brep/types-parsers
@@ -9,6 +9,7 @@
#define BREP_TYPES_PARSERS
#include <brep/types>
+
#include <brep/options-types>
namespace brep
diff --git a/brep/types-parsers.cxx b/brep/types-parsers.cxx
index f7f1c1b..39c9b42 100644
--- a/brep/types-parsers.cxx
+++ b/brep/types-parsers.cxx
@@ -5,6 +5,7 @@
#include <brep/types-parsers>
#include <brep/types>
+
#include <brep/options>
using namespace std;