aboutsummaryrefslogtreecommitdiff
path: root/web/apache/service
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-04-23 12:43:52 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-04-23 12:43:52 +0200
commita20443c285dabdec8d2ee740500c62e31ad90c7b (patch)
treeb18db4007e45f8db1f97c0d5abf78729138406ac /web/apache/service
parent370e361db628f60bca5509dcc354014569d56752 (diff)
Implement apache service
Diffstat (limited to 'web/apache/service')
-rw-r--r--web/apache/service94
1 files changed, 90 insertions, 4 deletions
diff --git a/web/apache/service b/web/apache/service
index 8dd21d8..688f8f1 100644
--- a/web/apache/service
+++ b/web/apache/service
@@ -5,22 +5,106 @@
#ifndef WEB_APACHE_SERVICE
#define WEB_APACHE_SERVICE
+#include <exception>
#include <string>
+#include <cassert>
+
+#include <httpd/httpd.h>
+#include <httpd/http_config.h>
#include <web/module>
+#include <web/apache/log>
+#include <web/apache/request>
+
namespace web
{
namespace apache
{
- class service
+ class service : ::module
{
public:
// Note that the module exemplar is stored by-reference.
//
template <typename M>
service (const std::string& name, const M& exemplar)
- : exemplar_ (exemplar), handle_ (&handle_impl<M>) {}
+ : ::module
+ {
+ STANDARD20_MODULE_STUFF,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &register_hooks<M>
+ },
+ name_ (name),
+ exemplar_ (exemplar)
+
+// Doesn't look like handle_ member is required at all.
+// handle_ (&handle_impl<M>)
+ {
+ // instance<M> () invented to delegate processing from apache request
+ // handler C function to service non static member function.
+ // This appoach resticts number of service objects per module
+ // implementation class with just one instance.
+ //
+ service*& srv = instance<M> ();
+ assert (srv == nullptr);
+ srv = this;
+ }
+
+ template <typename M>
+ static service*&
+ instance () noexcept
+ {
+ static service* instance;
+ return instance;
+ }
+
+ template <typename M>
+ static void
+ register_hooks (apr_pool_t *pool) noexcept
+ {
+ ap_hook_handler (&request_handler<M>, NULL, NULL, APR_HOOK_LAST);
+ }
+
+ template <typename M>
+ static int
+ request_handler (request_rec* r) noexcept
+ {
+ auto srv = instance<M> ();
+
+ if (!r->handler || srv->name_ != r->handler)
+ return DECLINED;
+
+ request req (r);
+ log l(r);
+
+ // As soons as M (), handle () and flush () can throw need to handle
+ // exceptions here.
+ //
+ try
+ {
+ M m (static_cast<const M&> (srv->exemplar_));
+ static_cast<module&> (m).handle (req, req, l);
+ return req.flush();
+ }
+ catch (const std::exception& e)
+ {
+ l.write (nullptr, 0, __PRETTY_FUNCTION__, APLOG_ERR, e.what ());
+ }
+ catch (...)
+ {
+ l.write (nullptr,
+ 0,
+ __PRETTY_FUNCTION__,
+ APLOG_ERR,
+ "unknown error");
+ }
+
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
//@@ Implementation calls handle_ function pointer below:
//
@@ -28,6 +112,7 @@ namespace web
//
private:
+/*
template <typename M>
static void
handle_impl (request& rq, response& rs, log& l, const module& exemplar)
@@ -35,9 +120,10 @@ namespace web
M m (static_cast<const M&> (exemplar));
static_cast<module&> (m).handle (rq, rs, l);
}
-
+*/
+ std::string name_;
const module& exemplar_;
- void (*handle_) (request&, response&, log&, const module&);
+// void (*handle_) (request&, response&, log&, const module&);
};
}
}