// file : web/apache/service -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC // license : MIT; see accompanying LICENSE file #ifndef WEB_APACHE_SERVICE #define WEB_APACHE_SERVICE #include #include #include #include #include #include #include #include namespace web { namespace apache { class service : ::module { public: // Note that the module exemplar is stored by-reference. // template service (const std::string& name, const M& exemplar) : ::module { STANDARD20_MODULE_STUFF, nullptr, nullptr, nullptr, nullptr, nullptr, ®ister_hooks }, name_ (name), exemplar_ (exemplar) // Doesn't look like handle_ member is required at all. // handle_ (&handle_impl) { // instance () 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 (); assert (srv == nullptr); srv = this; } template static service*& instance () noexcept { static service* instance; return instance; } template static void register_hooks (apr_pool_t *pool) noexcept { ap_hook_handler (&request_handler, NULL, NULL, APR_HOOK_LAST); } template static int request_handler (request_rec* r) noexcept { auto srv = instance (); 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 (srv->exemplar_)); static_cast (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: // // handle_ (rq, rs, l, exemplar_); // private: /* template static void handle_impl (request& rq, response& rs, log& l, const module& exemplar) { M m (static_cast (exemplar)); static_cast (m).handle (rq, rs, l); } */ std::string name_; const module& exemplar_; // void (*handle_) (request&, response&, log&, const module&); }; } } #endif // WEB_APACHE_SERVICE