Introduction
This article presents an introduction to the new version of proposed ‘Application’ library to boost.org. This new version is based on ‘aspect’ concept and is labeled as 0.4.x version.
Warning!
Some time ago, I wrote 2 articles based on version 0.3.
Creating a Work Queue
http://www.codeproject.com/Articles/664709/Creating-a-Work-Queue-Thread-Pool-Application-Usin
Note that an updated sample of this code is present in the new version of library (0.4) in example/uuid_client_server folder.
Create a Windows Service Application Using the Boost.Application Library
http://www.codeproject.com/Articles/662221/Create-a-Windows-Service-Application-Using-the-Boo
Note that an updated sample of this code is present in the new version of library (0.4) in example/work_queue folder.
Note that version 0.3 is no longer maintained! Version 0.4 is now maintained and receives regular updates.
Feedback
If you are a Boost user, and use Boost Mailing Lists, please provide your feedback about the library, directly on list. (Specify if you think the library should be accepted as part of boost.org.)
If you are a CodeProject user, please provide your feedback about the library directly on this page.
Bugs
If you find any BUGS, please send them to me at re.tf@acm.org.
Caution
The Boost.Application
is not yet an official Boost C++ library. It wasn't reviewed and can't be downloaded from www.boost.org. This beta is available to boost community to know the real interest and get comments for refinement. The intention is to submit the library for formal review, if the community thinks that it is interesting!
What is Boost.Application
Boost.Application
provides an application environment, or starting point to any people that want a basic infrastructure to build a system application on Windows or Unix Variants (e.g. Linux, MacOS).
Boost.Application
allows users to extend library functionality too, e.g. in this article, an Apache Httpd Module will be constructed as an “Boost Application Mode”.
An important concept of Boost.Application
is the 'aspects', that was proposed by 'Vicente J. Botet Escriba'. An “aspect concept” allows easy extension and customization of library components.
Boost.Application
provides many useful ready-to-use features, e.g:
- Run application as Windows Service
- Run application as UNIX/POSIX Daemon
- Plugin extension system
- Process(executable) Single instance Instantiation support
- Application SIGNAL/Callbacks customization
- Windows Service Setup feature
- Application Mode extension (that will be presented in this article)
- And many others
Boost.Application Resources
You can download the library from GitHub here.
An online documentation (under construction) is available here.
Library Official ‘Application Modes’
An ‘application mode’ is a ready to use feature that is offered by the library, in this version we have 2 official application modes (types):
- Common Application: This kind of application is an usual Interactive Terminal/Console Application.
- Server Application: This kind of application generates a Service (Windows), or a background process/Daemon (Unix).
This article will present how to extend library modes, it shows how to create a new simple ‘application mode’ to be used on Apache Web Server. With this ‘mode’ ready, the user can use it to generate any Apache Content Generator Module.
This is not official “library mode”, it is only a sample that illustrates how to extend library functionality. The resultant mode is very simple and doesn't expose all Apache Httpd Server API functionality. We will only implement a simple ‘Content Generator’ that supports the HTTP GET VERB!
0. Basic Setup
This library is not an official Boost.org library yet, and it uses other 2 not official libraries too, then the installation is not too easy.
1) The first step is to download the last version of boost and build it.
The build process of boost is not very easy too, but a good documentation is provided, refer to this link.
Or you can check this good article to help with build.
2) The second step is to download:
Boost.Application
(https://github.com/retf/Boost.Application/zipball/master) Boost.TypeIndex
(https://github.com/apolukhin/type_index/zipball/master) Boost.Singularity
(https://github.com/cppmaven/Singularity/zipball/master)
You can unzip each of it on your ‘c:\’ or other directory. We will configure Visual Studio Project to find these directories later!
Note that Boost.org is moving to git, thus the folder structure of libraries can change in future, refer to boost.org to know more!
1. Apache HTTP Web Server
The Apache Web Server is one of the most deployed Web Server today. This article presents how to use Boost.Application
library to create a way to extend Apache Web Server.
The Apache Server comprises a relative small core, and a lot of modules. Modules commonly held on a /modules directory are loaded at runtime. This article shows how to build a new application mode for “Boost.Application
”, that can be used to generate new ‘Apache Content Generator Module’.
1.1 Install Apache
You need to install Apache with include files.
You can download a Apache (2.3) for Windows here.
The screen below shows how to install Apache:
Important Note: In this article, the focus platform is Windows, but if you are a UNIX/LINUX user you can adapt this to your platform. “Boost.Application
” is Multiplatform, like any Boost library.
2. Setup a Visual Studio Project
The Visual Studio 2012 will be used to build the project, and all provided samples are for this version only. All code and projects are provided; check the download link on top of page.
2.1 Create Visual Studio Project skeletons to Apache Module.
Open Visual Studio, and create a Win32 Project. On ‘Application Settings’, select ‘DLL and ‘Empty Project’’.
2.2 On project, open properties window and add needed include directories to “C/C++ -> General -> Additional Include Directories”
The needed directories are:
Name Directories (example)
Your Main Boost C:\boost_1_54_0
Your Boost.Application E:\project.boost.app.v4.4
Your Boost.TypeIndex E:\type_index
Your Boost.Singularity E:\singularity
Your Apache API/APR C:\Program Files (x86)\Apache Software Foundation\Apache2.2\include
Note that your directories may have different names and locations.
2.3 On project, open properties window again, and add boost libs directories to “Linker -> General -> Additional Library Directories”
Note that when you build boost, the common place to libs are: e.g.: C:\boost_1_54_0\stage\lib.
2.4 We need do something to Apache “Linker -> General -> Additional Library Directories”
2.5 On project, add a new source file called “main.cpp”, and a header called “mymode.hpp”
3. Boost.Application -> Application Mode
As previously discussed, by default (at this first version), Boost.Application
provides two ready to use application modes: common and server application modes. In a general way, user will use one of these modes (types) to build a server or a terminal application. If provided modes don’t accomplish what the user desires, the user needs to extend the library mode.
The ‘application mode’ extension is the most advanced feature of Boost.Application
, and a new mode in a general way, needs work with some 3rdpart API, e.g. on Windows, the ‘server’ mode encapsulate and abstract to final user the Windows Service API.
In our case, we will work (encapsulate on the new mode) the Apache API, we will use Apache Portable Runtime (APR) inside our mode.
In the diagram below, we have a schematic diagram of the components of “Boost.Application
”, is highlighted in red which we modify/add.
For complete reference, refer to this link.
4. Starting Our Application Mode
On ‘main.cpp’, we will have our client code, and on “mymode.hpp” we will have our mode implementation.
At this point, it is good you take a look at the roadmap to learn how a simple application is made:
http://www.dokfile.com/appbeta4/docs/libs/application/doc/html/boost_application/roadmap.html
We will create a new mode to be used in step “H”.
4.1 Application Mode Introduction
Basically, an “Application Module” is composed of one ‘mode class’, which needs to have a defined structure (constructor, and methods) and a collection of ‘aspects’.
An ‘aspect’ can be any class, but “Boost.Application
” provides some base class that allows us to create a special type of ‘aspects’, e.g. a callback (handler) aspect.
To know more, refer to this link.
In our case, we will have one aspect to handle ‘apache log’, one to “web application name”, one for “content type” and the last will be our handler that will be called when a GET
request arrives.
5. Our Aspects (Number 4 on Diagram)
Here, I will present the implementation of all aspects to out mode.
5.1 Log Aspect
This aspect will provide log functionality to the final user. Take a look at:
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\logs
Inside this folder, we have many logs. Our “log aspect” will provide to user a way to use this log!
httpd.exe: Could not reliably determine the server's fully qualified domain name, using 192.168.0.9 for ServerName
.
[Wed Dec 11 09:38:05 2013] [notice] Apache/2.2.25 (Win32) configured -- resuming normal operations
<span style="font-size: 9pt;">
[Wed Dec 11 09:38:05 2013] [notice] Server built: Jul 10 2013 01:52:12 </span>
<span style="font-size: 9pt;">
[Wed Dec 11 09:38:05 2013] [notice] Parent: Created child process 6836
</span><span style="font-size: 9pt;">
[Wed Dec 11 09:38:12 2013] [warn] Page requested! Boost.Application! </span>
Apache log sample
class apache_log
{
friend class apache2_httpd_mod;
public:
apache_log(request_rec *r)
: r_(r) { }
void error(const std::string& msg)
{
ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r_->server, msg.c_str());
}
void information(const std::string& msg)
{
ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, 0, r_->server, msg.c_str());
}
void warning(const std::string& msg)
{
ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_WARNING, 0, r_->server, msg.c_str());
}
private:
request_rec *r_;
};
The apache_log Aspect.
5.2 Web Application Name Aspect
This aspect is used to identify our application on Apache, thus Apache can know if it handles our request or decline.
e.g.: http://localhost:8080/boostapp
The ‘boostapp
’ is our web application name.
class web_app_name
{
friend class apache2_httpd_mod;
public:
web_app_name(const std::string& web_app_name)
: web_app_name_ (web_app_name)
{}
private:
std::string web_app_name_;
};
The web_app_name Aspect
5.3 Content Type Aspect
This aspect is used to identify our content that will be pushed to browser client.
e.g.: "text/html;charset=ascii
"
class content_type
{
friend class apache2_httpd_mod;
public:
content_type(const std::string& my_content_type)
: content_type_ (my_content_type)
{}
private:
std::string content_type_;
};
The content_type Aspect
5.4 GET VERB Handler Aspect
This aspect is the most important, it will allow the final user of our mode to tie a custom ‘content generator’ handler to HTTP GET
VERB.
class http_get_verb_handler : public handler<std::string>
{
public:
http_get_verb_handler(const parameter_callback& callback)
: handler<std::string>(callback) {}
http_get_verb_handler(const singleton_callback& callback)
: handler<std::string>(callback) {}
};
The http_get_verb_handler Aspect
Note that we inherit from ‘boost::application::handler<:string>
’.
To know more about provided handlers, refer to this link.
6. Implement our Aspects (Number 2 on Diagram)
The ‘Application Mode’ is a class that will be initiated by ‘boost::application::launch
’ function. On our mode design, each request that arrives will launch a new apache2_httpd_mod
! Here, the mode designer is free to do anything.
class apache2_httpd_mod
{
public:
static int mode()
{
static int id = new_run_mode<int>();
return id;
}
template <typename Application, typename RequestRec>
apache2_httpd_mod(Application& myapp, RequestRec &rr,
context &cxt, boost::system::error_code& ec)
: error_(OK)
{
}
template <typename Application, typename RequestRec>
apache2_httpd_mod(Application& myapp, RequestRec &rr,
boost::singularity<context> &cxt, boost::system::error_code& ec)
: error_(OK)
{
}
int run() { return error_; }
protected:
};
The apache2_httpd_mod mode skeleton
Note that all ‘modes’ need respect these signatures.
The ‘mode
’ method is used to identify a mode, and we have 2 constructors, one that supports singularity, and the other that will receive a ‘context
’ as parameter, and ‘run
’ method that in our case returns one status code to client.
After that, the designer of the module is free to add any other method that is necessary. Let’s do this now:
class apache2_httpd_mod
{
public:
static int mode()
{
static int id = new_run_mode<int>();
return id;
}
template <typename Application, typename RequestRec>
apache2_httpd_mod(Application& myapp, RequestRec &rr,
context &cxt, boost::system::error_code& ec)
: error_(OK)
{
handle_request(myapp, rr, cxt);
}
template <typename Application, typename RequestRec>
apache2_httpd_mod(Application& myapp, RequestRec &rr,
boost::singularity<context> &cxt, boost::system::error_code& ec)
: error_(OK)
{
handle_request(myapp, rr, cxt.get_global());
}
int run() { return error_; }
protected:
template <typename Application, typename RequestRec>
void handle_request(Application& myapp, RequestRec &rr, context &cxt)
{
if(!cxt.find<run_mode>())
{
cxt.insert<run_mode>(
csbl::make_shared<run_mode>(mode()));
}
if(!cxt.find<status>())
{
cxt.insert<status>(
csbl::make_shared<status>(status::running));
}
csbl::shared_ptr<web_app_name> appname = cxt.find<web_app_name>();
if(!appname)
{
error_ = DECLINED; return;
}
if (strcmp(rr.handler, appname->web_app_name_.c_str()))
{
error_ = DECLINED; return;
}
if(rr.method_number != M_GET)
{
error_ = HTTP_METHOD_NOT_ALLOWED; return;
}
csbl::shared_ptr<http_get_verb_handler> http_get_verb =
cxt.find<http_get_verb_handler>();
if(http_get_verb)
{
cxt.insert<apache_log>(csbl::make_shared<apache_log>(&rr));
csbl::shared_ptr<content_type> contenttype =
cxt.find<content_type>();
if(contenttype)
ap_set_content_type(&rr, contenttype->content_type_.c_str());
else
ap_set_content_type(&rr, "text/html;charset=ascii");
handler<std::string>::parameter_callback* parameter = 0;
if(http_get_verb->callback(parameter))
{
ap_rputs((*parameter)(cxt).c_str(), &rr); return;
}
handler<std::string>::singleton_callback* singleton = 0;
if(http_get_verb->callback(singleton))
{
ap_rputs((*singleton)().c_str(), &rr); return;
}
}
cxt.find<status>()->state(status::stoped);
error_ = HTTP_INTERNAL_SERVER_ERROR;
}
private:
int error_;
};
Full apache2_httpd_mod mode that uses Apache APR
6.1 Export all to Apache be aware of our mode
To do this, we will implement a MACRO that the final user will need to add on “.cpp” file.
#define BOOST_APPLICATION_APACHE_REGISTER_TEST_MY_MODE(h, m) \
extern "C" { \
void boost_application_register_hooks(apr_pool_t *p) \
{ \
ap_hook_handler(h, NULL, NULL, APR_HOOK_MIDDLE); \
} \
\
module AP_MODULE_DECLARE_DATA m = { \
STANDARD20_MODULE_STUFF, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
boost_application_register_hooks \
}; }
Export Macro
6.2 Mode Conclusion
Now we have our mode ready to use. Now, our role is no more as ‘Mode Designer’, now our role will be ‘Mode User’ (client/final user)
7. Using the New ‘Mode’
Here, I will present how the final/client user can use our new mode.
7.1 Create an Application Functor Class
On our ‘main.cpp’, we will create our functor
class.
class my_apache2_httpd_content_generator_mod
{
public:
int operator()(application::context& context)
{
return 0;
}
std::string get(application::context& context)
{
context.insert<content_type>(
boost::make_shared<content_type>("text/html;charset=ascii"));
std::stringstream htm;
htm.str("");
htm << "<html>"
<< " <head>"
<< " <title>Boost.Application Test</title>"
<< " </head>"
<< ""
<< " <body>"
<< " <h1> Hello Boost.Application Version "
<< application::library_version_string() << "!"
<< " </h1>"
<< " <br/>"
<< " Apache HTTPd Mod."
<< " <br/>"
<< " </body>"
<< "</html>"
;
boost::shared_ptr<apache_log> apachelog = context.find<apache_log>();
if(apachelog)
{
apachelog->warning("Page requested!");
}
return htm.str();
}
};
Application Functor Class
In ‘get
’ method, we will generate our content, in this case the content will be a simple HTML page. We will use our ‘log aspect’ tool!
7.2 Implement “main” Function
This function will be called by Apache on a request, and we use it to setup our application mode at run-time.
extern "C" int myhandle(request_rec *r)
{
my_apache2_httpd_content_generator_mod app;
application::context app_context;
app_context.insert<web_app_name>(
boost::make_shared<web_app_name>("boostapp"));
handler<std::string>::parameter_callback my_http_get_verb
= boost::bind<std::string>(
&my_apache2_httpd_content_generator_mod::get, &app, _1);
app_context.insert<http_get_verb_handler>(
boost::make_shared<
http_get_verb_handler>(my_http_get_verb));
return application::launch<apache2_httpd_mod>(app, *r, app_context);
}
Our main function (myhandler)
Apache Web Server calls this function passing a ‘request_rec
’ that we will pass to our mode.
Then, we create our application functor
class, our context, that will hold all of our aspects. To know more about context, refer to this link.
After that, we use the mode aspects that we just created. Note that we bind our ‘get
’ method to our ‘http_get_verb_handler
’ aspect.
The last step is to tie all together and run the ‘content generator’, we do this using “application::launch
<apache2_httpd_mod>” function that receives our mode as template parameter.
7.3 Register our ‘main (myhandler)’ Function
The final step is to register our main function, using our MACRO.
BOOST_APPLICATION_APACHE_REGISTER_TEST_MY_MODE(myhandle, my_boost_app_mod)
Register myhandler
8. Configure httpd.cong
Now is the time to configure our ‘httpd.cong’ file.
This file is located in ‘/conf’, in my case:
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\conf
8.1 Add our module on httpd.cong
Open file and add this:
#LoadModule version_module modules/mod_version.so
#LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule my_boost_app_mod "C:\Users\Renato Tegon Forti\Desktop\mymod\Debug\mymod.dll"
<Location /boostapp>
SetHandler boostapp
</Location>
Httpd Configuration
Change "C:\Users\Renato Tegon Forti\Desktop\mymod\Debug\mymod.dll" to your path.
9. Test
Go to your Apache folder, and start Apache as Admin.
9.1 Open your Browser and request page, and you need see:
10. Conclusion
Here, I show how the user can extend the Library, many other ready to use features are available, one that I like a lot is plug-in system. Take a look at the documentation.
And please send your comments and let me know if you liked this article or not. Also, please feel free to give suggestions and report bugs .