-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdmbcs-micro-server.texi
876 lines (663 loc) · 32.9 KB
/
dmbcs-micro-server.texi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
\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" name="arg_1"/> x <input type="text" name="arg_2"/>
= <input type="text" id="result" value="[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)
{
Hyper_Tags tags;
tags.add ("result",
query.get ("arg_1", 0) * query.get ("arg_2", 0));
Http_Server::return_html (socket,
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