cppcms::worker_thread & cppcms::application
Table of Contents
Roles
worker_thread
and application
are very similar classes that gives user similar APIs but they have important differences:
worker_thread
has single instance in each worker thread or process, it is usually not used directly, but it is referenced by several application
classes.
In many cases, we need to have more then one application or sub application in our process (for example wiki and forum or users panel and administration panel).
All these application share same controls like access to cache and sessions, access for HTTP requests --- all these stored in worker_thread
class.
In terms of API, both classes are very similar with the difference that worker_thread
stores actual data and application
stores references to this data in worker_thread
.
In most of cases developers should derive their own classes
from cppcms::application
and not from cppcms::worker_thread
.
Constructors
worker_thread(manager const &s); application(worker_thread &w);
worker_thread
and application
constructors should receive a reference to manager
and primary worker_thread
.
For example:
class my_application : public application { my_application(worker_thread &w) : application(w) { ...
Public Members
cppcms::application
worker_thread &worker; url_parser &url; manager const &app; cgicc::Cgicc *&cgi; cgicc::CgiEnvironment const *&env; cgicc_connection *&cgi_conn; cache_iface &cache; session_interface &session; ostream &cout; boost::signal<void()> &on_start; boost::signal<void()> &on_end;
cppcms::worker_thread
url_parser url; manager const &app; cgicc::Cgicc *cgi; cgicc::CgiEnvironment const *env; cgicc_connection *cgi_conn; cache_iface cache; session_interface session; ostream cout; boost::signal<void()> on_start; boost::signal<void()> on_end;
Description
url_parser url
It is a class responsible on binding various handlers to different requested url. For example:
url.add("^/test$",&app::test,this);
See
cppcms::url_parser
for reference.manager const &app
-- access tocppcms::manager
class. Usually used to fetch configuration values. For example:int num=app.config.ival("my_app.number");
cgicc::Cgicc *cgi
-- access tocgicc::Cgicc
class of cgicc library that gives you a content of HTTP query.It is usually used together with form processing:
some_content c; c.some_form.load(*cgi);
cgicc::CgiEnvironment const *env
-- environment of cgicc query. Seecgicc::CgiEnvironment
cgicc_connection *cgi_conn
--- access to low level CGI API. Input stream, output stream environment variables.Generally it should be used only in case we need access to some CGI environment variable unsupported by cgicc. For example:
string encodings=cgi_conn->env("ACCEPT_ENCODING");
cache_iface cache
-- access to cache API. See:cache_iface
session_interface session
-- access to sessions API. See:session_interface
ostream cout
--- the stream for output content of the cgi process (without headers). It is generally used via templates system, however it can be used directly for creating HTML or any other output content.For example, create csv:
set_header(new HTTPContentHeader("text/csv")); cout<<"n,n!"<<endl; cout<<"0, 1"<<endl; cout<<"1, 1"<<endl; cout<<"2, 2"<<endl; cout<<"3, 6"<<endl;
boost::signal<void()> on_start, on_end
--- these are the signals that application can connect itself in order to perform certain tasks when new query comes, independently from URL.Various application running in same thread may attach many signals.
For example:
class my_app: public application { int user_id; string user_name; void start() { if(session.is_set("user_id")) { user_id=session.get<int>("user_id"); user_name=fetch_user_name(user_id); } else { user_id=-1; user_name="visitor"; } } void end() { // Cleanup all user data user_id=0; user_name.clear(); } ... my_app() { on_start.connect(bind(&start,this)); on_end.connect(bind(&end,this)); ... }
Note: callbacks connected to
on_end
should never throw -- think of them as of destructors.
Public Member Functions
HTTP Headers
void set_header(cgicc::HTTPHeader *h)
-- set newly created HTTP Header.Notes:
- Default header is
cgicc::HTTPHTMLHeader
. - It removes previous header and all cookies associated with it. Thus, always set header and then set cookies.
- The pointer to header is freed by an application.
For example:
set_header(new HTTPContentHeader("text/csv"));
See cgicc::HTTPHeader for details.
- Default header is
void set_cookie(cgicc::HTTPCookie const &c)
--- set HTTP Cookie to current header.See: cgicc::HTTPCookie for details of cookies creation.
cgicc::HTTPHeader &header()
-- return current header.void add_header(string s)
-- add general header. For example:add_header("X-Sendfile: " + filename);
CgiCC API does not allow rendering several headers together, thus --
add_header(string)
removes this limitation. For example:add_header("Status: 302 Found"); set_header(new HTTPRedirectHeader(new_location));
Fine Granted Output Control
These functions are available starting from CppCMS 0.0.3
void set_user_io()
-- allows user to write directly to output stream instead of internal buffer.Calling this functions forces saving all session data and all headers are immediately written to the output stream. Thus, updating session data or changing headers would not take an effect after this function is called.
Note: You should use output stream from
cgi_conn
instead of ordinarycout
member ofworker_thread
for output.This function can be used for generating big output that should not be saved in internal buffers and compressed.
For example, streaming of image::
ifstream file("big.png"); set_header(new cgicc::HTTPContentHeader("image/png")); set_user_io(); ostream &cout=cgi_conn->cout(); for(;;) { file.read(&buffer.front(),1024); cout.write(&buffer.front(),file.gcount()); if(file.eof()) break; } file.close();
void no_gzip()
-- disable output compression for this page.It is used to prevent from CppCMS compress output even if browser accepts gzip encoding. It can be used mostly for serving binary or already compressed data.
Note: If you cache your output you must call this function before you try to fetch the data from the cache, otherwise the data would be served compressed even if you do not want this.
For example:
no_gzip(); set_header(new cgicc::HTTPContentHeader("image/png")); if(cache.fetch_page("small_image")) return; /// generate some image cache.store_page("small_image");
Localization
Setting language dynamically:
void set_lang()
-- Set default application language.void set_lang(string const &)
-- Set application language. This call affects all other calls ofgettext()
,ngettext()
and language of template rendering.
Translating strings:
char const *gettext(char const *s)
-- translate string "s".char const *ngettext(char const *s,char const *p,int n)
-- translate single/plural form of string forn
.
Note: In contrary to GNU gettext library, these functions are thread safe --- you can use different languages in different threads safely.
Working with different domain:
transtext::trans const *domain_gettext(string const &d)
-- returns pointer to gettext dictionary for specific domain.transtext::trans
has two public functions important to user: gettext and ngettext with same signatures as above.For example:
transtext::trans const *tr=domain_gettext("views"); string username=tr->gettext("username");
This function has no effect on current gettext dictionary.
Templates rendering
Setting skins
void use_template(string s="");
Set template. If no specified, default is used. For example:
if(session.is_set("skin")) use_template(session["skin"]);
Rendering output
void render(string teml,base_content &c); void render(string view,string teml,base_content &c); void render(string teml,base_content &c,ostream &o); void render(string view,string teml,base_content &c,ostream &o);
Render specific function templ
using content c
. If view
specified, render using view view
instead of default.
If ostream &o
specified render template to o
instead of cout. The recent is useful to create partial renderings and caching them. For example:
ostringstream tmp; render("sidebar",content,tmp); cache.store_frame("sidebar",tmp.str());
cppcms::application member functions
Virtual Member functions
Note: these functions are used only in cppcms::application
class where user can override default functionality. They does not exist in worker_thread
or have different semantics.
virtual void on_404()
--- default handler that is called in case of URL that does not match any given pattern.You may display your own page there or redirect to general correct url.
virtual void main()
--- this is the main function. It has following default implementation:on_start(); if(url.parse()<0) { on_404(); } on_end();
If you decide to override this function, don't forget ti call
on_start
andon_end
semantics. For example, you can try to handle there sql connection errors:on_start(); for(i=0;i<2;i++) { try { if(url.parse()<0) { on_404(); } break; } catch(sql_connection_error &e) { if(i==0) sql.reconnect(); else no_connection_page(); } } on_end();
Notes: Only one application class may override it's
main()
because only one main function is called. Rest applications working in same thread are called using url bindings.
Public Template Member Functions
These functions are used for easier connection of SQL libraries to an application. Assuming you have persistent SQL connection per thread.
These functions implemented as template functions in order to prevent linking with specific libraries.
SOCI
template<typename SQL> void soci_load(SQL &sql)
Connect to SQL database using SOCI.
CppCMS Configuration parameters:
soci.conn
soci connection string calling:sql.open(conn);
soci.driver
,soci.params
-- connect to soci calling:sql.open(driver,params);
DbiXX
template<typename SQL> void dbixx_load(SQL &sql);
Connects to database using dbixx library, it uses following parameters:
dbixx.driver
--- the SQL driver used for dbixx, for example "sqlite3".
All other parameters are taken from configuration using prefix given in dbixx.driver
. For example:
dbixx.driver="sqlite3" sqlite3.dbname="wikipp.db" sqlite3.sqlite3_dbdir="./db/"
Refer to libdbi-drivers documentation pages for setting up correct parameters.