876 lines
33 KiB
Text
876 lines
33 KiB
Text
\input texinfo
|
|
@setfilename dmbcs-micro-server.info
|
|
@include version.texi
|
|
@settitle The dmbcs-micro-server Library Reference Manual
|
|
@syncodeindex tp fn
|
|
@syncodeindex pg fn
|
|
|
|
@copying
|
|
This is the reference manual for the dmbcs-micro-server C++ library
|
|
(version @value{VERSION}, @value{UPDATED}).
|
|
|
|
Copyright @copyright{} 2018 Dale Mellor
|
|
|
|
@quotation
|
|
Permission is granted to copy, distribute and/or modify this document
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation; either version 2 of the License, or (at your
|
|
option) any later version. The text of the license can be found in the
|
|
section entitled ``Copying''.
|
|
@end quotation
|
|
@end copying
|
|
|
|
@dircategory Libraries
|
|
@direntry
|
|
* dmbcs-micro-server: (dmbcs-micro-server). C++ CGI utility library.
|
|
@end direntry
|
|
|
|
@setchapternewpage odd
|
|
@titlepage
|
|
@title The DMBCS micro-server Library Reference Manual
|
|
@subtitle Version @value{VERSION}
|
|
@subtitle @value{UPDATED}
|
|
@author Dale Mellor
|
|
|
|
@page
|
|
@vskip 0pt plus 1filll
|
|
@insertcopying
|
|
@end titlepage
|
|
|
|
|
|
@node Top
|
|
@summarycontents
|
|
@contents
|
|
@page
|
|
|
|
|
|
@ifnottex
|
|
@top The micro-server Library
|
|
@insertcopying
|
|
@end ifnottex
|
|
|
|
@menu
|
|
* Introduction::
|
|
* Using the library::
|
|
* Reference::
|
|
* Examples of Use::
|
|
* Hints on how the library might be used in a real application::
|
|
|
|
@detailmenu
|
|
--- The Detailed Node Listing ---
|
|
|
|
Introduction
|
|
|
|
* HTTP Web Services::
|
|
* Our Choice of Name::
|
|
* Your Choice of Library::
|
|
* Outline of Library:: An overview of the library's implementation
|
|
|
|
Using the library
|
|
|
|
|
|
Reference
|
|
|
|
* The utility functions::
|
|
* The Query_String class::
|
|
* The Hyper_Tags class::
|
|
* The Http_Server class::
|
|
|
|
The Query_String class
|
|
|
|
* MACs::
|
|
* Constructors::
|
|
* Methods::
|
|
* Functions::
|
|
|
|
The Hyper_Tags class
|
|
|
|
* Constructors_::
|
|
* Methods_::
|
|
* Functions_::
|
|
|
|
The Http_Server class
|
|
|
|
* Constructor__::
|
|
* Functions__::
|
|
|
|
Examples of Use
|
|
|
|
* Simple example -- Online multiplier:: A simple application of the library
|
|
|
|
Hints on how the library might be used in a real application
|
|
|
|
* Web-site skins:: Web sites which provide a user-selected `look-and-feel'
|
|
* Other inheritence:: Other ideas
|
|
|
|
@end detailmenu
|
|
@end menu
|
|
|
|
@node Introduction, Using the library, Top, Top
|
|
@chapter Introduction
|
|
|
|
This document introduces, defines and exemplifies use of the
|
|
dmbcs-micro-server C++ library, providing services to applications for
|
|
processing and responding to requests from a web browser, including the
|
|
possibility of making the application a stand-alone web server in its
|
|
own right (a `micro-server').
|
|
|
|
@menu
|
|
* HTTP Web Services:: Introduction to CGI and web servers
|
|
* Our Choice of Name:: Use of `DMBCS'
|
|
* Your Choice of Library:: Some gentle advice
|
|
* Outline of Library:: An overview of the library's implementation
|
|
@end menu
|
|
|
|
@node HTTP Web Services, Our Choice of Name, Introduction, Introduction
|
|
@section HTTP Web Services
|
|
A CGI program is a program, written in any language, which conforms to
|
|
the Common Gateway Interface (CGI). It is a program executed by a web
|
|
server (on the server machine), and is passed information about the
|
|
request from the user through the UNIX environment. It is left to the
|
|
program to interpret the user's requirements and to produce on its
|
|
standard output channel a HTML document which the web server will
|
|
relay back to the user's browser for display on his console.
|
|
|
|
CGI programs are thus very flexible and amenable to lots of jobs.
|
|
Some of them are very small, amounting to only a couple of lines of an
|
|
interpreted language to slurp a file from the local storage and send
|
|
it straight back to the browser (which is essentially what a web
|
|
server would normally do but this allows the programmer to do so in a
|
|
more customized way). On the other hand, some CGI programs are
|
|
extremely large consisting of hundreds of thousands of lines of code
|
|
which may interact with a database and other third-party systems (such
|
|
as payment gateways) and do some real work on behalf of the user,
|
|
before sending the results of the transactions along for the user's
|
|
perusal.
|
|
|
|
This project came from a CGI program of the latter description. Because
|
|
of its size, complexity and the anticipated load (number of users), it
|
|
was decided very early on that it would be written in a proper
|
|
programming language which could be compiled optimized to run on the
|
|
bare metal of the available computer system, whatever that is. Thus it
|
|
would have to be C or C++. While the original implementation had been
|
|
in C for political reasons, it has since been ported to the more
|
|
convenient C++. As a side-effect of this development, the parts of the
|
|
system which deal specifically with the business of being a CGI program
|
|
have been abstracted and encapsulated, and then they were syphoned off
|
|
into their own separate library; this was further extended to provide
|
|
the functions of a self-contained web server. This is now being offered
|
|
for general use.
|
|
|
|
The result is a library which can be used to inject a self-contained web
|
|
server into an arbitrary C++ code base, opening up the interface to such
|
|
a legacy program to the modern world, without needing to also build the
|
|
infrastructure to serve such a program to the public (although in
|
|
practice infrastructure needs to be built for other reasons---like
|
|
security and virtualization---but the self-contained scheme allows for
|
|
greater flexibility and better functional isolation).
|
|
|
|
|
|
@node Our Choice of Name, Your Choice of Library, HTTP Web Services, Introduction
|
|
@section Our Choice of Name
|
|
The micro-server library was written from scratch since 2004 as part of
|
|
a large internet project. The requirement for a C++ framework for
|
|
undertaking this task is very common, and thus it is no surprise that
|
|
other efforts already exist, notably the GNU cgicc project.
|
|
|
|
Some consideration was given to the name of this project. At first it
|
|
was going to be called cgicc2, but that carries the implication that
|
|
it somehow carries on from the GNU cgicc project, and that it is both
|
|
a development and enhancement of it. This is definitely not the case,
|
|
but a parallel development, completely different but solving the same
|
|
problems. Unfortunately appending any number or even letter carries
|
|
some implication of sequencing, and if the two projects continue (as
|
|
they should) to be developed then some imbalance would occur in the
|
|
rivalry. Such is definitely not the intention, but for the two
|
|
projects to be seen as separate. Choice of one or other framework for
|
|
any particular project should be based on what the framework offers,
|
|
not what letters happen to come in its name.
|
|
|
|
Thus it is decided to mark this particular library with the string
|
|
'DMBCS': all code appears inside the namespace 'DMBCS::Micro_Server' and
|
|
the include file is called 'dmbcs-micro-server.h'; the project is
|
|
formally known as the 'dmbcs-micro-server' C++ library.
|
|
|
|
|
|
@node Your Choice of Library, Outline of Library, Our Choice of Name, Introduction
|
|
@section Your Choice of Library
|
|
We offer only this advice: look at the API provided by all the available
|
|
libraries, and consider the nature of the working framework (paradigm)
|
|
that that implies; choose the library that seems most appropriate for
|
|
your project: the one that you will feel most comfortable working with.
|
|
|
|
|
|
@node Outline of Library, , Your Choice of Library, Introduction
|
|
@section Outline of Library
|
|
The library consists of a high-level wrapper and two workhorse classes.
|
|
@code{Http_Server} interfaces with multiple clients and delegates
|
|
processing of their requests to registered callback functions, which
|
|
make direct use of the following workhorses. @code{Query_String} looks
|
|
after the part of the CGI interface which passes from the browser to the
|
|
CGI program and provides methods specifically for interpreting the
|
|
arguments from the browser's query string, and @code{Hyper_Tags} looks
|
|
after the part of the CGI interface which passes back from the CGI
|
|
program to the browser, and displays the results of the user's request;
|
|
this deals with updating template HTML files with some dynamic content
|
|
before passing the result to the web server for eventual transmission to
|
|
the browser.
|
|
|
|
|
|
@node Using the library
|
|
@chapter Using the library
|
|
To re-iterate: all code in this library comes in the namespace
|
|
'DMBCS::Micro_Server' and the header which introduces all of the
|
|
functionality is 'dmbcs-micro-server.h'.
|
|
|
|
A project would generally consist of a template HTML file with markers
|
|
where dynamically-generated content needs to be placed, a .css file
|
|
which should be injected into the file or provided by the server as an
|
|
inclusion target in the HTML, a .js file containing code that should run
|
|
client-side to implement part of the functionality of the web site, and
|
|
a (micro-) web server which runs continually, listens for client
|
|
connections, and provides generated HTML files and JSON data strings on
|
|
demand of the client.
|
|
|
|
@menu
|
|
@end menu
|
|
|
|
@node Reference, Examples of Use, Using the library, Top
|
|
@chapter Reference
|
|
|
|
@menu
|
|
* The utility functions:: Useful functions needed by web applications
|
|
* The Query_String class:: For processing the user's arguments
|
|
* The Hyper_Tags class:: For substituting dynamic content into HTML
|
|
* The Http_Server class:: To implement a micro-server in your own app
|
|
@end menu
|
|
|
|
@node The utility functions, The Query_String class, Reference, Reference
|
|
@section The utility functions
|
|
Introductory text here.
|
|
|
|
@deftypefun string slurp_file_with_error (const std::string &@var{file_name}) throw (Slurp_Error)
|
|
|
|
This function will attempt to open the file named file_name (which may
|
|
be a complete path to the file), and read the whole lot into a string.
|
|
If any errors occur in the process, a Slurp_Error object will be thrown
|
|
(these exception objects do not convey any information back to the
|
|
application).
|
|
@end deftypefun
|
|
|
|
@deftypefun string slurp_file (const std::string &@var{file_name})
|
|
|
|
This function will attempt to open file @var{file_name} (which may be a
|
|
full path), and will slurp the entire contents (which are presumably a
|
|
hyper-tag'd template file) into a string. If any errors occur, an empty
|
|
string will be produced, and a message printed on the standard error
|
|
channel to indicate the name of the file which has failed.
|
|
|
|
In the majority of applications of this function, in the majority of
|
|
calls, the error condition thrown from the function above will not
|
|
happen; it would be regarded as an infrastructure build problem rather
|
|
than a run-time error if a known file were not accessible. Thus it is
|
|
wasteful to worry about and deal with the error at global level--outside
|
|
the library--, rather let the program carry on and provide a message to
|
|
the user's console about the missing file (the fact that the problem
|
|
occurred will be obvious!) Once it is known which file has failed, the
|
|
remedy will be equally obvious.
|
|
@end deftypefun
|
|
|
|
@deftypefun string htmlize_quotes (string && @var{input})
|
|
|
|
Any occurrence of `` in @var{input} will be replaced by `@code{"};'
|
|
@end deftypefun
|
|
|
|
@deftypefun string htmlize (string && @var{input})
|
|
|
|
All occurrences of HTML-special characters (<>&") will be replaced with
|
|
entity representations.
|
|
|
|
The main purpose of this method is to alleviate the possibility of
|
|
injection attacks into a web-site; if any part of a page is generated
|
|
from user-supplied input there is the danger that the user might be
|
|
savvy enough to get JavaScript to execute there! But the function is
|
|
quite generally useful when it is known that a string needs to appear
|
|
verbatim in a web page, regardless of its contents, and thus ought to be
|
|
used whenever a string is added to a set of @code{Hyper_Tag}s.
|
|
@end deftypefun
|
|
|
|
@deftypefun string strip_leading_space (string && @var{input})
|
|
|
|
Replace all sequences of white space at the start of all lines with a
|
|
single space character.
|
|
|
|
HTML recognizes all sequences of white space outside of quotes as a
|
|
single space separator. Thus sequences of white space at the
|
|
beginning of lines (which are used by web programmers to give a nice
|
|
aesthetic indentation) are a waste of bandwidth. This function will
|
|
remove all such occurrences from @var{input}.
|
|
@end deftypefun
|
|
|
|
@deftypefun string escape_quotes (string @var{input})
|
|
|
|
Replace all occurrences of quotation marks and escapes with escaped
|
|
versions, where the escape character is the back-slash.
|
|
|
|
This function will put an escape ('\') in front of ''', '''', or '\'
|
|
which occur in @var{input}, and is useful (essential when dealing with
|
|
user-supplied input) to ensure that strings do not mess up SQL
|
|
statements.
|
|
@end deftypefun
|
|
|
|
@deftypefun string decode_url (string @var{url})
|
|
|
|
This function will replace '+' with ' ', and any %-escaped character
|
|
codes in the @var{url} with the ASCII equivalent.
|
|
|
|
This will produce a plain string, decoded from strings passed from forms
|
|
or EcmaScript on web pages passed through parameter lists in URI's, as
|
|
provided within the context of this library by the @code{Query_String}
|
|
object.
|
|
@end deftypefun
|
|
|
|
@deftypefun string hexalize (unsigned char const *const @var{buffer}, size_t const @var{buffer_size})
|
|
|
|
Return an ASCII string containing the hexadecimal representation of the
|
|
octets in the given @var{buffer}. The @var{buffer_size} is the number of
|
|
octets to decode.
|
|
@end deftypefun
|
|
|
|
@deftypefun string getenv (string const & @var{env})
|
|
|
|
Return the value of the environment variable called @var{env}, or an
|
|
empty string if the variable does not exist in the environment.
|
|
|
|
This is a convenience wrapper around the system @code{getenv} call,
|
|
adapting it to the use of strings.
|
|
@end deftypefun
|
|
|
|
@node The Query_String class
|
|
@section The Query_String class
|
|
A Query_String object is a std::map<std::string, std::string> object
|
|
in which the keys are the variables passed in the URL query string
|
|
part and the values are the values from that query string. Methods
|
|
are defined which interrogate the class in details more specific to
|
|
the CGI problem, and allow for values to be extracted in either string
|
|
or a numeric form, as expected by the CGI program.
|
|
|
|
@menu
|
|
* MACs::
|
|
* Constructors::
|
|
* Methods::
|
|
* Functions::
|
|
@end menu
|
|
|
|
@node MACs, Constructors, The Query_String class, The Query_String class
|
|
@subsection MACs
|
|
|
|
@node Constructors
|
|
@subsection Constructors
|
|
|
|
@deftp {Constructor} Query_String ()
|
|
|
|
The null constructor, only useful if you are intending to build up a
|
|
new query string for eventual inclusion into some part of a HTML page.
|
|
@end deftp
|
|
|
|
@deftp {Constructor} Query_String (const char *const *const @var{env})
|
|
|
|
The real workhorse constructor. The argument @var{env} should be the
|
|
environment variable passed to the CGI's main routine as the third
|
|
argument. This will create an object which represents the information
|
|
passed to the CGI program via the query string, whether it were sent
|
|
via the GET or the PUT protocols. The object returned can
|
|
subsequently be used to interrogate the user's request string.
|
|
@end deftp
|
|
|
|
@node Methods
|
|
@subsection Methods
|
|
|
|
@deftp {Method} void Query_String::add (const std::string &@var{name}, const T &@var{value})
|
|
|
|
This method will add an entry into the Query_String with key
|
|
@var{name} and value a string representation of @var{value}. The type
|
|
T of @var{value} may be anything that can be passed into a
|
|
std::ostream object via the << operator.
|
|
@end deftp
|
|
|
|
@deftp {Method} void Query_String::add (const std::string &@var{name}, const Query_String &@var{input}, const T &@var{fallback})
|
|
|
|
This method will add an entry into the current Query_String which is a
|
|
copy of the entry in the @var{input} Query_String, unless such entry
|
|
does not exist in which case a key @var{name} with value a std::string
|
|
representation of @var{fallback} will be added to the current
|
|
Query_String. The type T of @var{fallback} may be anything that can
|
|
be passed to the << operator of a std::ostream object.
|
|
@end deftp
|
|
|
|
@deftp {Method} bool Query_String::posted () const
|
|
|
|
Returns TRUE if the query string had been sent to the CGI program via
|
|
the POST protocol, FALSE otherwise (which case would presumably have
|
|
been caused by use of the GET protocol).
|
|
@end deftp
|
|
|
|
@deftp {Method} T Query_String::get (const std::string &name, const T &fallback) const
|
|
|
|
This gets the value associated with the key @var{name} from the query
|
|
string, unless no such key was present in which case @var{fallback} is
|
|
returned. Note that the type of value returned is the same as that of
|
|
@var{fallback}, thus @var{fallback} serves the dual role of defining
|
|
the fallback value and determining the return type of the function.
|
|
@end deftp
|
|
|
|
@deftp {Method} std::vector <int> Query_String::get_list (const std::string &name) const
|
|
|
|
In the case that a query string value corresponds to a multiple choice
|
|
selection on the HTML form, it will be a comma-separated string of
|
|
selected values. This function will return a vector comprised of
|
|
these values, interpreted as integers. If there is no key @var{name}
|
|
in the query string, then the returned vector will have no elements
|
|
(zero length).
|
|
@end deftp
|
|
|
|
@deftp {Method} std::vector <int> Query_String::get_checked_array (const std::string &NAME) const
|
|
|
|
@end deftp
|
|
|
|
@deftp {Method} bool Query_String::has (const std::string &NAME) const
|
|
|
|
This method returns TRUE if the @var{name} was a variable present in
|
|
the query string, FALSE otherwise.
|
|
@end deftp
|
|
|
|
@deftp {Method} bool Query_String::mac_verified () const
|
|
|
|
This method will return TRUE only if there was a MAC present in the
|
|
query string, and the MAC was valid. Otherwise FALSE will be
|
|
returned.
|
|
@end deftp
|
|
|
|
@node Functions
|
|
@subsection Functions
|
|
|
|
@deftypefun static string Query_String::add_mac (string @var{input})
|
|
|
|
This static class member will add a cryptographic MAC onto any string,
|
|
but this is only meaningful for composed query strings.
|
|
@end deftypefun
|
|
|
|
|
|
@node The Hyper_Tags class
|
|
@section The Hyper_Tags class
|
|
Whereas a HTML document contains markup tags expressed as labels between
|
|
angle brackets (possibly in pairs), so a micro-server template file
|
|
contains dynamic content holders expressed as labels between square
|
|
brackets. The Hyper_Tags class contains methods for replacing single
|
|
tags with some dynamically-generated content, and for selectively
|
|
keeping or removing sections of the template bracketed between pairs of
|
|
hyper tags.
|
|
|
|
A Hyper_Tags object should be considered a container of tag
|
|
definitions. The CGI program will typically build up a list of such
|
|
definitions in the container, until all the work is done when the
|
|
template file is read in from local storage and the Hyper_Tags object
|
|
is instructed to make all the changes in one go before sending the
|
|
result to the server and hence to the user's browser.
|
|
|
|
@menu
|
|
* Constructors_::
|
|
* Methods_::
|
|
* Functions_::
|
|
@end menu
|
|
|
|
@node Constructors_, , The Hyper_Tags class, The Hyper_Tags class
|
|
@subsection Constructors_
|
|
@deftp {Constructor} Hyper_Tags ()
|
|
|
|
The class only has the one, default, constructor, which returns an
|
|
empty object waiting to be filled with tag definitions.
|
|
@end deftp
|
|
|
|
@node Methods_, , Constructors_, The Hyper_Tags class
|
|
@subsection Methods_
|
|
@deftp {Method} void Hyper_Tags::harden_last ()
|
|
|
|
Normally, a later tag definition would overrule any earlier ones when
|
|
substitutions are finally made into a template file. However, if it
|
|
is desired that the last tag added should be the final tag definition
|
|
on substitution, then it can be `hardened' by calling this method.
|
|
@end deftp
|
|
|
|
@deftp {Method} bool Hyper_Tags::has (const std::string &@var{name}) const
|
|
|
|
This method returns TRUE if a tag with the given @var{name} has been
|
|
registered with the Hyper_Tags object. In all other cases it returns FALSE.
|
|
@end deftp
|
|
|
|
@deftp {Method} Hyper_Tags &Hyper_Tags::add (const Hyper_Tags &@var{registry}, const int @var{harden} = 0)
|
|
|
|
This method copies all the tag definitions contained in @var{registry}
|
|
into the current object, and returns a reference to the current
|
|
object. If the optional @var{harden} argument is passed a non-zero
|
|
value, then all the incumbent tag definitions will be hardened, as per
|
|
the discussion of the harden_last () method above.
|
|
@end deftp
|
|
|
|
@deftp {Method} Hyper_Tags &Hyper_Tags::add (const std::string &@var{name}, string @var{substitution_text})
|
|
|
|
One of the main methods of the class. Declares that, in the final
|
|
substitutions, any parts of the template file which look like
|
|
``[@var{name}/]'' should be replaced with @var{substitution_text}.
|
|
|
|
The return is a reference to the current object.
|
|
@end deftp
|
|
|
|
@deftp {Method} Hyper_Tags &Hyper_Tags::add (const std::string &@var{name}, const int value)
|
|
|
|
Declares that tags called @var{name} in the template file be replaced
|
|
with a string representing the integer @var{value}. The return is a
|
|
reference to the current object.
|
|
@end deftp
|
|
|
|
@deftp {Method} Hyper_Tags &Hyper_Tags::add (const std::string &@var{name}, const double @var{value}, const int @var{precision} = 4)
|
|
|
|
Declares that tags called @var{name} be replaced with a string
|
|
representing the floating-point @var{value}, with at least
|
|
@var{precision} significant figures. The return is a reference to the
|
|
current object.
|
|
@end deftp
|
|
|
|
@deftp {Method} Hyper_Tags &add (const std::string &@var{name}, Query_String &@var{q_s}, const T &@var{fallback})
|
|
|
|
Declares that tags called @var{name} be replaced with a value from
|
|
@var{q_s} with the same name if this exists, or with @var{fallback}
|
|
otherwise. The type T of fallback should be one of std::string, int,
|
|
or double. The return is a reference to the current object.
|
|
@end deftp
|
|
|
|
@deftp {Method} void add_int_list (const std::string &@var{name}, I @var{begin}, I @var{end})
|
|
|
|
Here, I is an iterator type over an STL container of int's. This
|
|
method declares that tags named @var{name} be substituted with a
|
|
comma-separated list of integer values.
|
|
@end deftp
|
|
|
|
@deftp {Method} void add_date (const std::string &@var{name}, const time_t &@var{time}, const std::string &@var{format})
|
|
|
|
Specifies that tags named @var{name} be replaced with a string
|
|
representing the date indicated by the UNIX @var{time} object. The
|
|
conversion takes place according to @var{format}, which is described
|
|
in the strftime () libc manual.
|
|
@end deftp
|
|
|
|
@deftp {Method} void add_file (const std::string &@var{name}, const std::string &@var{file_name})
|
|
|
|
Specifies that tags named @var{name} in the template HTML file be
|
|
replaced with the entire contents of the file called @var{file_name}
|
|
in the file system.
|
|
@end deftp
|
|
|
|
@deftp{Method} void add_passthrough_tag (const Query_String &@var{query_string}, ...)
|
|
|
|
The trailing arguments are a list of const char *const, terminated
|
|
with a NULL pointer. This method specifies that contents of the HTML
|
|
template file which look like ``[pass-through/]'' be replaced with a
|
|
set of lines which look like ``<input type=``hidden'' name=``name''
|
|
value=``value''/>'' where the @var{names} are taken from the list of
|
|
arguments to the function, and the @var{__values__} are taken from the
|
|
@var{query_string} variables with the same names. Thus, if the tag in
|
|
the template file is contained within ``<form>'' markup elements, the
|
|
current values in the query string will be propagated into any query
|
|
string that the new form produces.
|
|
@end deftp
|
|
|
|
@deftp{Type} enum Hyper_Tags::Section_Keep @{ KEEP_SECTION, LOSE_SECTION @}
|
|
@end deftp
|
|
|
|
@deftp{Method} Hyper_Tags §ion (const std::string &@var{name}, const Section_Keep &@var{keep})
|
|
|
|
This method declares the action to be taken when a pair of tags like
|
|
``[@var{name}]'' and ``[/@var{name}]'' are seen in a template file.
|
|
If @var{keep} is KEEP_SECTION, then the tags are simply removed from
|
|
the file leaving the contents between the tags intact. If @var{keep}
|
|
is LOSE_SECTION then the tags and all the text between them is removed
|
|
from the file.
|
|
@end deftp
|
|
|
|
@deftp{Method} string Hyper_Tags::substitute (string @var{html_template}, int @var{repeat} = 1)
|
|
|
|
One of the main methods of the class. This will go through
|
|
@var{html_template} and replace any hyper tags which have been
|
|
registered with the substitution text that has been declared as the
|
|
replacement. If a tag is seen in the @var{html_template} which has
|
|
not been registered with the current object, then this tag will remain
|
|
intact in the template.
|
|
|
|
Additionally, any pairs of tags seen in @var{html_template} which have
|
|
been registered as a section will be removed, possibly removing also
|
|
all the text between the tags, according to the registered behaviour.
|
|
@end deftp
|
|
|
|
|
|
@node Functions_, , Methods_, The Hyper_Tags class
|
|
@subsection Functions_
|
|
|
|
@deftypefun static string Hyper_Tags::strip_loose_tags (string @var{input})
|
|
|
|
It may happen that, after processing, a HTML template string still
|
|
contains some hyper tags which have not been substituted. This static
|
|
function will injudiciously remove any such tags, thus eliminating any
|
|
ugliness from the page sent back to the user.
|
|
@end deftypefun
|
|
|
|
|
|
@node The Http_Server class, , The Hyper_Tags class, Reference
|
|
@section The Http_Server class
|
|
|
|
@menu
|
|
* Constructor__::
|
|
* Functions__::
|
|
@end menu
|
|
|
|
@node Constructor__, Functions__, The Http_Server class, The Http_Server class
|
|
@subsection Constructor__
|
|
|
|
@deftypefun Http_Server::Http_Server (const int @var{socket}, const
|
|
std::map<std::string, std::function<void (Query_String, int)> @var{methods})
|
|
|
|
Create a HTTP server to listen on the @var{socket}. Processing for
|
|
requests will be delegated to the @var{methods}, referenced by the
|
|
HTTP-call path name via the @code{map}. When called, the @var{methods}
|
|
will be passed a @code{Query_String} object and a socket on which a
|
|
response must be sent; methods are provided in the Http_Server namespace
|
|
to facilitate with this.
|
|
|
|
Please see the example application to see how this is used in practice.
|
|
@end deftypefun
|
|
|
|
|
|
@node Functions__, , Constructor__, The Http_Server class
|
|
@subsection Functions__
|
|
|
|
@deftypefun bool tick (Http_Server &@var{server}, const long @var{wait_us})
|
|
|
|
Cause the @var{server} to act on a single instruction from a web client,
|
|
waiting up to @var{wait_us} micro-seconds for such a request to appear.
|
|
|
|
The return is usually @code{TRUE}, but may be @code{FALSE} if the
|
|
listening socket goes away (this is a mechanism that could be used by a
|
|
request processing function to terminate the server frow within).
|
|
|
|
In practice this method is called repeatedly, @emph{ad infinitum}.
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_html (const int @var{socket},
|
|
const std::string &@var{html})
|
|
|
|
This method sends the @var{html} to the socket, dressed up as a valid
|
|
response to a HTTP request for data.
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_text (const int @var{socket},
|
|
const std::string &@var{text})
|
|
|
|
This method sends the @var{text} to the socket, dressed up as a valid
|
|
response to a HTTP request for data.
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_pdf (const int @var{socket},
|
|
const std::string &@var{pdf})
|
|
|
|
This method sends the @var{pdf} to the socket, dressed up as a valid
|
|
response to a HTTP request for data. The `string' is actually
|
|
understood as a buffer of arbitrary octects here.
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_json (const int @var{socket},
|
|
const std::string &@var{json})
|
|
|
|
This method sends the @var{json} to the socket, dressed up as a valid
|
|
response to a HTTP request for data.
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_bad (const int @var{socket})
|
|
|
|
This method sends an empty payload to the socket, dressed up as a
|
|
@emph{valid} response to a HTTP request for data (it would generally be
|
|
taken by an Ecmascript application to be a `bad' response to a request
|
|
for data).
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_png (const int @var{socket},
|
|
const std::string &@var{png})
|
|
|
|
This method sends the @var{png} to the socket, dressed up as a valid
|
|
response to a HTTP request for data. The `string' is actually
|
|
understood as a buffer of arbitrary octects here.
|
|
@end deftypefun
|
|
|
|
|
|
@deftypefun void Http_Server::return_svg (const int @var{socket},
|
|
const std::string &@var{svg})
|
|
|
|
This method sends the @var{svg} to the socket, dressed up as a valid
|
|
response to a HTTP request for data. The `string' is actually
|
|
understood as a buffer of arbitrary octects here.
|
|
@end deftypefun
|
|
|
|
|
|
@node Examples of Use, Hints on how the library might be used in a real application, Reference, Top
|
|
@chapter Examples of Use
|
|
We don't start with the tradition hello, world program as this would
|
|
not demonstrate in any way the dynamic nature of CGI programming! The
|
|
simplest example we can think of allows the user to input two numbers
|
|
and returns the product of them, and the full code for this is
|
|
provided in the next section.
|
|
|
|
@menu
|
|
* Simple example -- Online multiplier:: A simple application of the library
|
|
@end menu
|
|
|
|
@node Simple example -- Online multiplier
|
|
@section Simple example -- Online multiplier
|
|
|
|
The following is provided as the simplest code to demonstrate use of the
|
|
dmbcs-micro-server library, not to inform of any coding style or quality
|
|
system approach. We assume a standard GNU system with recent
|
|
@code{make}, @code{bash}, @code{gcc}, etc.
|
|
|
|
Start with the HTML file @code{calc.html}
|
|
|
|
@verbatim
|
|
<html>
|
|
<head><title>Multiplier</title></head>
|
|
<body><h1>Multiplier</h1>
|
|
<form action="compute" method="GET" id="calc">
|
|
<input type="text" id="arg_1"/> x <input type="text" id="arg_2"/>
|
|
= <input type="text" id="result">[result/]</input>
|
|
<br>
|
|
<input type="submit">CALCULATE</input>
|
|
</form>
|
|
</body>
|
|
</html>
|
|
@end verbatim
|
|
|
|
And the C++ source file @code{calc.cc}
|
|
|
|
@verbatim
|
|
#include <dmbcs-micro-server.h>
|
|
|
|
using namespace DMBCS::Micro_Server;
|
|
|
|
|
|
/* This function both serves up the basic HTML page, and
|
|
* performs the multiplication and injects the result into the
|
|
* HTML. */
|
|
void home_page (Query_String const &query, int const socket)
|
|
{
|
|
auto tags = Hyper_Tags {};
|
|
|
|
add (tags,
|
|
"result",
|
|
query.get ("arg_1", 0) * query.get ("arg_2", 0));
|
|
|
|
Http_Server::return_html (substitute (tags,
|
|
slurp_file ("calc.html")));
|
|
}
|
|
|
|
|
|
int main ()
|
|
{
|
|
auto server = Http_Server {2022,
|
|
{ {"", home_page},
|
|
{"compute", home_page} }};
|
|
|
|
for (;;) tick (server, 1000000);
|
|
|
|
return 0;
|
|
}
|
|
@end verbatim
|
|
|
|
then the @code{makefile}
|
|
|
|
@verbatim
|
|
CXXFLAGS = `pkg-config --cflags dmbcs-micro-server`
|
|
LDFLAGS = `pkg-config --libs dmbcs-micro-server`
|
|
@end verbatim
|
|
|
|
Then at the command line type
|
|
|
|
@verbatim
|
|
make calc
|
|
./calc
|
|
@end verbatim
|
|
|
|
then point a browser at @code{http://localhost:2022/} and use the simple
|
|
calculator (don't try to do anything funny: the code has been kept
|
|
deliberately simple and doesn't do any error checking). Note that an
|
|
answer can be obtained directly with a URL like
|
|
@code{http://localhost:2022/compute?arg_1=3&arg_2=4}.
|
|
|
|
|
|
@node Hints on how the library might be used in a real application, , Examples of Use, Top
|
|
@chapter Hints on how the library might be used in a real application
|
|
While the basic library as it is serves perfectly well for small CGI
|
|
programs, the library was derived from a larger project. From this
|
|
experience, it is seen that many large projects will want to produce
|
|
specializations of the classes and utility functions provided by the
|
|
library for the particular project. The following are some specific
|
|
details about how the library was enhanced in the original project.
|
|
|
|
@menu
|
|
* Web-site skins:: Web sites which provide a user-selected `look-and-feel'
|
|
* Other inheritence:: Other ideas
|
|
@end menu
|
|
|
|
@node Web-site skins, Other inheritence, Hints on how the library might be used in a real application, Hints on how the library might be used in a real application
|
|
@section Web-site skins
|
|
The underlying paradigm promoted by the library is one where the
|
|
programmer supplies template HTML files which the CGI program
|
|
populates with extra dynamic content. This opens the possibility of
|
|
supplying the same dynamic content into different templates, for
|
|
example where a web site allows the user to choose a favorite `skin',
|
|
or `look-and-feel', then each template file would exist in different
|
|
forms to provide all the different skins available. In this case, the
|
|
library can be extended by ensuring that whenever a template is
|
|
slurped from local storage for use, it is the template appropriate for
|
|
the user's choice of skin that is pulled up.
|
|
|
|
In the original project, this was achieved by placing all templates
|
|
for a skin into a single directory to which the CGI program has access
|
|
(it was actually a sub-directory underneath the cgi-bin directory, and
|
|
the web server was configured to *not* allow direct access from a
|
|
browser to these files).
|
|
|
|
The main modification was to add a new utility function in the
|
|
project's namespace
|
|
|
|
@code{string slurp_file (const std::string &skin,
|
|
const std::string &filename)}
|
|
|
|
which is called by the program in lieu of slurp_file, and
|
|
ensures that the file from the correct skin directory is chosen,
|
|
calling through to the library function to get the eventual work
|
|
done. To complete the effect, it is also necessary to derive a new
|
|
class from Hyper_Tags with the following additional methods
|
|
|
|
@code{blah, blah, blah}
|
|
|
|
(The Query_String class works completely as is; it may be
|
|
convenient to introduce this into the projects own namespace with a
|
|
|
|
@code{typedef Query_String Query_String;}
|
|
|
|
line in a project header file.)
|
|
|
|
@node Other inheritence, , Web-site skins, Hints on how the library might be used in a real application
|
|
@section Other inheritence
|
|
|
|
@bye
|