// file : web/apache/service -*- C++ -*- // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef WEB_APACHE_SERVICE #define WEB_APACHE_SERVICE #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, M& exemplar) : ::module { STANDARD20_MODULE_STUFF, nullptr, nullptr, nullptr, nullptr, nullptr, ®ister_hooks }, name_ (name), exemplar_ (exemplar) { init_directives (); // instance () is invented to delegate processing from apache // request handler C function to the service non static member // function. This appoach resticts number of service objects per // specific module implementation class with just one instance. // service*& srv (instance ()); assert (srv == nullptr); srv = this; } ~service () { delete [] cmds; } template static service*& instance () noexcept { static service* instance; return instance; } template static void register_hooks (apr_pool_t*) noexcept { // The config_finalizer() function is called at the end of Apache // server configuration parsing. // ap_hook_post_config (&config_finalizer, NULL, NULL, APR_HOOK_LAST); // The worker_initializer() function is called right after Apache // worker process is started. Called for every new process spawned. // ap_hook_child_init (&worker_initializer, NULL, NULL, APR_HOOK_LAST); // The request_handler () function is called for each client request. // ap_hook_handler (&request_handler, NULL, NULL, APR_HOOK_LAST); } template static int config_finalizer (apr_pool_t*, apr_pool_t*, apr_pool_t*, server_rec* s) noexcept { auto srv (instance ()); bool& parsed (srv->options_parsed_); if (!parsed) { log l (s); srv->exemplar_.version (l); parsed = true; } return OK; } template static void worker_initializer (apr_pool_t*, server_rec* s) noexcept { log l (s); instance ()->init_worker (l); } 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->server); return srv->template handle (req, l); } private: void init_directives (); void init_worker (log& l) noexcept; static const char* parse_option (cmd_parms* parms, void* mconfig, const char* args) noexcept; const char* add_option (const char* name, optional value); template int handle (request& r, log& l) noexcept; private: std::string name_; module& exemplar_; option_descriptions option_descriptions_; name_values options_; bool options_parsed_ = false; }; } } #include #endif // WEB_APACHE_SERVICE