|
Boost-Commit : |
From: lists.drrngrvy_at_[hidden]
Date: 2007-08-22 22:43:20
Author: drrngrvy
Date: 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
New Revision: 38862
URL: http://svn.boost.org/trac/boost/changeset/38862
Log:
Adding to the documentation regarding reply -> response changes; plus minor notes about cookies; also some gramatical/spelling/accuracy fixes. Meta-variables section has been changed to only refer to `meta` when it actually *is* meta-data; changed tables to reflect new forms of variable access functions.
Added:
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/cookies.qbk (contents, props changed)
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/variables.qbk (contents, props changed)
Text files modified:
sandbox/SOC/2007/cgi/libs/cgi/doc/src/cgi.qbk | 4 +
sandbox/SOC/2007/cgi/libs/cgi/doc/src/future_development.qbk | 34 ++++++++-------
sandbox/SOC/2007/cgi/libs/cgi/doc/src/introduction.qbk | 12 ++--
sandbox/SOC/2007/cgi/libs/cgi/doc/src/preface.qbk | 15 ++++--
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/building.qbk | 8 +-
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/protocols.qbk | 37 +++++++---------
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial.qbk | 2
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp | 86 +++++++++++++++++++++++++++------------
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/accepting.qbk | 24 ++++++-----
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/loading.qbk | 82 ++++++++++++++++++++-----------------
sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/requests.qbk | 12 ++--
11 files changed, 182 insertions(+), 134 deletions(-)
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/cgi.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/cgi.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/cgi.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -20,6 +20,8 @@
]
]
+[def __this__ ["FSCGI"]] [/ name of the library]
+
[def __cgi__ [@http://en.wikipedia.org/wiki/Common_Gateway_Interface CGI]]
[def __scgi__ [@http://en.wikipedia.org/wiki/Simple_Common_Gateway_Interface SCGI]]
[def __fcgi__ [@http://en.wikipedia.org/wiki/FastCGI FastCGI]]
@@ -63,7 +65,7 @@
[def __loading__ boost.cgi.ug.tutorial.loading]
[important
-This manual does [*not] document a library that is a part of __Boost__. The major part of it has been developed this summer as part of the Google Summer of Code, '[@http://code.google.com/soc GSoC07]'. Everything from here on in is alpha-grade, some bits more than others; [link boost.cgi.preface.comments_and_support comments] are welcome.
+This manual does [*not] document a library that is a part of __Boost__. The major part of it has been developed this summer as part of the Google Summer of Code, '[@http://code.google.com/soc GSoC07]'. Everything from here on in is alpha-grade, some bits more than others; [link boost.cgi.preface.comments_and_support comments and bug reports] are welcome.
These documents are either hosted at [@http://sourceforge.net/projects/cgi/ sourceforge], or at [@http://svn.boost.org/svn/boost/browser/sandbox/SOC/2007/cgi svn.boost.org]. For free!
]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/future_development.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/future_development.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/future_development.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -17,9 +17,9 @@
[h4 FastCGI support.]
-FastCGI support is essential to any modern CGI library. There is currently ['no] known FastCGI library for C or C++ that aims to implement the complete [@http://www.fastcgi.com/devkit/doc/fcgi-spec.html FastCGI 1.0] specification.
+FastCGI support is essential to any modern CGI library. There is currently ['no] known FastCGI library for C or C++ that aims to implement the complete [@http://www.fastcgi.com/devkit/doc/fcgi-spec.html FastCGI 1.0] specification. Providing support for multiplexing FastCGI daemons is one of this library's major goals.
-There are a couple of issues that have yet to be worked out, but in general the new framework is known to 'fit' with all the details of FastCGI and lends itself to an efficient implementation (hopefully).
+There are a couple of issues that have yet to be worked out, but in general the new framework is known to 'fit' with all the details of FastCGI and should lend itself to an efficient implementation.
[h4 Access to error output streams]
@@ -42,7 +42,7 @@
[h4 Having `meta_*` functions return a `cgi::param` type instead of `std::string`]
-An advantage to this approach, for the functions that look up request meta-data, is that multiple values can be easily extracted from the same key, when they exist. Currently, a user must get the complete map of meta-data and use that themselves. Since environment meta-data can't be uniformly retrieved as a `cgi::map_type&` (since they are actually process-level environment variables, accessible only through `::getenv()`) this can be awkward.
+An advantage to this approach, for the functions that look up request meta-data, is that multiple values can be easily extracted from the same key, when they exist. Currently, a user must get the complete map of meta-data and use that themselves. [-Since environment meta-data can't be uniformly retrieved as a `cgi::map_type&` (since they are actually process-level environment variables, accessible only through `::getenv()`) this can be awkward.]
Another advantage is that a macro can be provided to turn on/off implicit conversion to `std::string`, which is in essence a form of tainting, akin to perl's taint mode.
@@ -51,9 +51,9 @@
Compare:
``
cgi::request req;
-cgi::reply rep;
+cgi::response resp;
-cgi::map::iterator iter = req.meta_form().find("number");
+cgi::map::iterator iter = req.form_().find("number");
if (iter != cgi::map::iterator::end())
{
rep<< "You picked no numbers...";
@@ -61,15 +61,15 @@
else
{
int sum(0);
- rep<< "Your numbers are: ";
+ resp<< "Your numbers are: ";
for(; iter != cgi::map::iterator::end(); ++iter)
{
- rep<< iter->second << " ";
+ resp<< iter->second << " ";
sum += boost::lexical_cast<int>(iter->second);
}
- rep<< std::endl
- << "Your numbers add up to: " << sum;
+ resp<< std::endl
+ << "Your numbers add up to: " << sum;
}
rep.send(req);
@@ -77,33 +77,35 @@
to:
``
cgi::request req;
-cgi::reply rep;
+cgi::response resp;
-cgi::param parm = req.meta_form("number");
+cgi::param parm = req.form_("number");
if (parm.empty())
{
- rep<< "You picked no numbers...";
+ resp<< "You picked no numbers...";
}
else
{
int sum(0);
for(; parm != parm.end(); ++parm)
{
- rep<< parm << " ";
+ resp<< parm << " ";
sum += parm.as<int>());
}
- rep<< std::endl
- << "Your numbers add up to: " << sum;
+ resp<< std::endl
+ << "Your numbers add up to: " << sum;
}
-rep.send(req);
+resp.send(req);
``
[h4 Concept Documentation]
Even though this library introduces very few new concepts, they are not currently documented. Links to Boost.Asio's concept documentation is also required (essentially as part of a reworking of the doxygen reference section).
+[/h4 Removing aCGI/CGI Divide]
+
[/h4 Support for wide characters]
[/The library generally works on octets, but there should be some way to ]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/introduction.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/introduction.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/introduction.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -14,12 +14,12 @@
int main(int, char**)
{
request req;
- reply rep;
+ response resp;
- rep<< "Hello there, Universe. "
- << "Oh wait, no, it's you " << req.meta_form("name")
- << ", isn't it?!";
- rep.send(req);
+ resp<< "Hello there, Universe. "
+ << "Oh wait, it's just you, " << req.form_("name")
+ << ", isn't it?!";
+ resp.send(req);
}
``
@@ -37,7 +37,7 @@
The __FastCGI__ and __SCGI__ protocols are essentially reworkings of CGI which remove this restriction. They offer other advantages too, the support of which - of widely varying quality and completeness ([-more [link __server_support__ here]]) - comes for most HTTP servers. These protocols add an extra layer to your CGI programs, as you now must manage the request queue.
-In return for the added complexity, your programs become complete servers, capable of handling arbitrary numbers of requests during each invocation (assuming they don't crash!). This gives you the freedom to keep database connections open between requests, or cache ready-parsed responses, for example. Processing of a client request can even be continued in the case of the client crashing - the reply can then be stored and given to them when they return - saving precious CPU cycles.
+In return for the added complexity, your programs become complete servers, capable of handling arbitrary numbers of requests during each invocation (assuming they don't crash!). This gives you the freedom to keep database connections open between requests, or cache ready-parsed responses, for example. Processing of a client request can even be continued in the case of the client crashing - the `response` can then be stored and given to them when they return - saving precious CPU cycles.
It might sound like a handful but, fortunately, management of the request queue can be largely isolated from the handling of each request. That means that after you have set up a 'server' (ie. something that gathers requests), requests can be handled in the same way as they would be with a conventional CGI program.
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/preface.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/preface.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/preface.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -13,11 +13,11 @@
[h3 Overview]
-Boost.CGI is a library for writing CGI programs in Standard C++. It can be used to write anything from simple 'adming scripts' to full-fledged, scalable applications. This library rests on top of and should appear familiar to users of Boost.Asio, a cross-platform networking library in boost-style C++. Currently the __cgi__, [-__scgi__ and __fcgi__] protocols are supported, within a framework that should allow code to be reused with as-yet-unwritten protocols without any real modification.
+Boost.CGI is a library for writing CGI programs in Standard C++. It can be used to write anything from simple 'admin scripts' to full-fledged, scalable applications. This library rests on top of and should appear familiar to users of Boost.Asio, a cross-platform networking library in boost-style C++. Currently the __cgi__, [-__scgi__ and __fcgi__] protocols are supported, within a framework that should allow code to be reused with as-yet-unwritten protocols without any real modification.
[h3 Motivation]
-C++ isn't a particularly common choice for CGI programming, although it is a powerful one and can be used to produce maintainable and uncompromisingly efficient applications with any feature possible in any other language.
+C++ isn't the language of choice for many CGI programmers, although it is a powerful one and can be used to produce maintainable and uncompromisingly efficient applications with any feature possible in any other language.
A complete discussion about the benefits of CGI programming in C++ is beyond the scope of this document, but here is a short list:
@@ -33,8 +33,11 @@
* C++ rarely misses out on access to new technologies: for instance, if a new RDBMS came out tomorrow, it would almost certainly ship with a C/C++ API. The same would not be true for most other languages.
+* Web applications can benefit from an enforced modular design.[footnote For an example design choice, see [@http://www.google.co.uk/search?hl=en&rlz=1B3GGGL_enGB234GB235&q=model+view+controller&btnG=Search&meta= Model-View-Controller].] C++'s flexibility with regard to object-oriented design patterns is highly-regarded and well documented.
-In these days of 'Web 2.0' - with web applications becoming increasingly complex and responsive (ie. asynchronous, vis-Ã -vis AJAX) all the while being required to scale boundlessly - the benefits of C++ begin to show.
+With web applications becoming increasingly complex and responsive (ie. asynchronous, vis-Ã -vis AJAX) all the while being required to scale boundlessly - the benefits of C++ begin to show.
+
+The generally poor support for CGI programming for C++ - most libraries are either unmaintained, or don't take advantage of modern C++ capabilities - has driven the development of this library. [-moremoremore]
[h3 How to use this manual]
@@ -48,7 +51,7 @@
[h5 Macros]
-Macros are prefixed with `BOOST_CGI_*`
+Macros are prefixed with `BOOST_CGI_*` .
[h5 Code snippets]
@@ -58,6 +61,8 @@
Use cases, example requests, puzzles and problems should be sent to the mailing list:
-* ''' cgi-talk @ lists.sf \.\ net''', or thereabouts.
+''' cgi-talk @ lists.sf \.\ net'''
+
+or thereabouts.
[endsect]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/building.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/building.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/building.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -7,7 +7,7 @@
[section Building]
-Boost.CGI is a header-only library (for now), but it relies on [link __boost_system__ Boost.System], which for now must be built.
+__this__ is a header-only library, but it relies on [link __boost_system__ Boost.System], which must be built.
[/h5 What you need:]
@@ -22,7 +22,7 @@
[
[Boost.Jam - `bjam`]
[No]
- [Download 'boost-jam' (precomiled versions are highly recommended) and make it accessible by putting it somewhere pointed to by your system's PATH.]
+ [Download 'boost-jam' (precomiled versions are highly recommended) and make it accessible to your system's PATH.]
]
[
[Boost.System]
@@ -31,7 +31,7 @@
2. Set the environment variable BOOST_ROOT on your system to the download location.
- 3. Go to the directory BOOST_ROOT and invoke `bjam` (see above), passing it `--with-system install` on the command line. This should finish without any fails.]
+ 3. Go to the directory BOOST_ROOT and invoke `bjam` (see above), passing it `--with-system --layout=system install` on the command line. This should finish without any fails.]
]
[
[Documentation]
@@ -46,7 +46,7 @@
[
[Examples]
[Yes]
- [The examples are a useful guide to uses of the library. They are also useful for testing your server configuration. They can all be found in the lib/cgi/example directory. Invoking `bjam` in the example directory should build all examples whereas invoking `bjam` in each sub-directory will build only the example contained therein.]
+ [There are some examples provided with the library in the `libs/cgi/example` directory. They are useful for testing your server configuration, which can be notoriously tricky. They can all be found in the lib/cgi/example directory. Invoking `bjam` in the example directory should build all examples whereas invoking `bjam` in each sub-directory will build only the example contained therein.]
]
]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/protocols.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/protocols.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/protocols.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -11,6 +11,10 @@
The protocols supported by this library are CGI (synchronous and asynchronous), FastCGI (aka. FCGI) and SCGI (aka. SimpleCGI).
+[note
+Synchronous and asynchronous CGI support are considered distinct within the library for now (*more*), so the latter is referred to explicitly as aCGI. SimpleCGI is generally shortened to SCGI while FastCGI is used verbatim.
+]
+
Purely to illustrate what each protocol offers, consider this list:
* CGI is for short programs that won't be run very often, or those that will be used by only a very small number of clients, such as admin 'scripts'. Here, having a long-running process might be wasteful.
@@ -21,10 +25,6 @@
* SCGI is essential where server-side support for FastCGI is either buggy (as it is with Apache + mod_fastcgi: use mod_fcgid instead if possible) or missing.
-[note
-Synchronous and asynchronous CGI support are considered distinct within the library for now (*more*), so the latter is referred to explicitly as aCGI. SimpleCGI is generally shortened to SCGI while FastCGI is used verbatim.
-]
-
[section:comparison Feature Comparison]
[table
@@ -47,14 +47,16 @@
['See also: __hello_world__]
-The first use of an `cgi::acgi_request` (or the shortcut `cgi::arequest`) shows the main difference:
+The two skeleton programs below illustrate the main differences between a `cgi::acgi::request` and a `cgi::cgi::request`:
``
#include <cgi/cgi.hpp>
+using namespace cgi::cgi;
+
int main()
{
- cgi::request req;
+ request req;
// use the request here
@@ -64,20 +66,21 @@
compares to:
``
#include <cgi/acgi.hpp>
+#include <boost/ref.hpp>
#include <boost/thread.hpp> // see __boost_thread__
+using namespace cgi::acgi;
+
int main()
{
// a __Service__ is needed to handle asynchronous operations
- cgi::cgi_service service;
-
- // possibly use an asynchronous acceptor here (see below)
+ service srv;
- // create a thread for async operations to be run in
- boost::thread thread(boost::bind(&cgi::cgi_service::run, service));
+ // create a background thread for async operations to be run in
+ boost::thread thread(boost::bind(&service::run, boost::ref(srv)));
// create a request from the cgi_service
- cgi::arequest req(service);
+ request req(srv);
// use the request here
// ...
@@ -89,21 +92,15 @@
}
``
-As is obvious, the main difference of CGI over aCGI is that a `cgi::request` (or the more explicit `cgi::cgi_request`) doesn't use a `cgi::io_service`, so CGI
-
-exists purely within the library and may become transparent in the future. In other words, both methods will work in the same way, with CGI acting as a shortcut to using aCGI.
-
[endsect]
[section:fcgi FastCGI]
FastCGI is a binary protocol that works very differently to CGI ['internally] and has many advantages. In bullet-point form, FastCGI programs:
-* are servers in themselves: they can persist indefinitely and can - at least in principle - handle any number of simultaneous requests.
-
-* communicate with an HTTP server with TCP sockets __ref_pipe_support__.
+* Are servers in themselves: they can persist indefinitely and can - at least in principle - handle any number of simultaneous requests. This can be used to great effect to all but eliminate program initialisation time, which usually prove to be a major bottleneck in short-run applications (such as AJAX scripts);
-One such advantage as allowing a single program handle an arbitrary number of requests, in any order, without having to stop and start between each.
+* Communicate with an HTTP server with TCP sockets __ref_pipe_support__. FastCGI daemons can run under different user id's to the server, have different access privileges or even run in remote locations.
[h4 How it Works]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -7,7 +7,7 @@
[section Tutorial]
-As mentioned in the [link __intro__ introduction], there are two ways of using this library: for 'scripting' and everything else.
+As mentioned in the [link __intro__ introduction], there are two ways of using this library: for 'scripting' and for 'everything else'.
The thing that differentiates 'scripts' from everything else is the [link __ProtocolService__ ProtocolService] (this is similar in use to an [link __asio_io_service__ `io_service`] for those familiar with __asio__).
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -3,54 +3,86 @@
using namespace cgi;
//[main
-/*` It is assumed you have included <boost/cgi/cgi.hpp> and are `using namespace cgi`. */
+/*`
+It is assumed you have included <boost/cgi/cgi.hpp> and are `using namespace cgi`.
+*/
+
int main(int,char**)
{
request req;
- /*` At this point, the environment variables are accessible. This includes cookie and form variables too, which by default are all parsed.
+/*`
+At this point, the environment variables are accessible. This includes cookie and form variables too, which by default are all parsed.
+
+The `response` class provides a streaming interface for writing replies. You ['can] write to the request object directly, but for now we're going to just use the `response`, which is simpler. Writing to a `response` is buffered - whereas writing to the request directly isn't - so if an error occurs, you can simply `clear()` the response and send an error message, which is much cleaner than sending half a response to the client, followed by "... Sorry, I just broke!".
+*/
+
+ response resp;
- The `reply` class provides a streaming interface for writing replies. You ['can] write to the request object directly, but for now we're going to just use the `reply`, which is simpler. Writing to a `reply` is buffered - whereas writing to the request directly isn't - so if an error occurs, you can simply `clear()` the reply and send an error message, which is much cleaner than sending half a reply to the client, followed by "... Sorry, I just broke!".
- */
- reply rep;
+/*`
+Let's assume you now want to check if the user has a cookie, "user_name", set. We get at it like this:
+*/
- /*` Say now you want to check if the user has a cookie, "user_name", set. We get at it like this: */
- std::string user_name( req.meta_cookie("user_name") );
+ std::string user_name( req.cookie_("user_name") );
+
+/*`
+If it's set, we'll be polite and say hello. If you are used to CGI programming, you'll notice the lack of any HTTP headers. If you don't want to bother with headers, a default header `'Content-type: text/plain'` is sent, followed by the usual HTTP end-of-line `'\r\n'` and a blank line which indicates the end of the headers and the start of content.
+*/
- /*` If it's set, we'll be polite and say hello. */
if (!user_name.empty())
{
- rep<< "Hello there, " << user_name << ". How are you?";
+ resp<< "Hello there, " << user_name << ". How are you?";
+
+/*`
+That's all we want to say for now, so just send this back and quit.
+*/
- /*` That's all we want to say for now, so just send this back and quit. */
- rep.send(req);
+ resp.send(req);
return 0;
}
- /*` If the cookie isn't set, we will check if the user has posted a __GET__/__POST__ form with their name. */
- user_name = req.meta_form("user_name");
+/*`
+If the cookie isn't set, we will check if the user has posted a __GET__/__POST__ form with their name.
+*/
+ user_name = req.form_("user_name");
if (!user_name.empty())
{
- /*` If they have told us their name, we should set a cookie so we remember it next time. Then we can say hello and exit. There are two ways to set a cookie: either directly using `req.set_cookie("user_name", user_name)` or the method below. Again, the request object isn't buffered, so we are going to keep using the `reply` in case something breaks and we end up not wanting to set the cookie. The cookie we set below will expire when the user closes their browser.
- */
- rep<< cookie("user_name", user_name)
- << "Hello there, " << user_name << ". You're new around here.";
+/*`
+If they have told us their name, we should set a cookie so we remember it next time. Then we can say hello and exit. There are two ways to set a cookie: either directly using `req.set_cookie("user_name", user_name)` or the method below. You can also send an expiry date for the cookie [rfc 822] and a path. Note that if you don't set a value for the cookie, the cookie will be deleted.
- rep.send(req);
- }
+Again, the request object isn't buffered, so we are going to keep using the `response` in case something breaks and we end up not wanting to set the cookie. The cookie we set below will expire when the client closes their browser.
+
+This time, we shall send a Date header. If we do this (ie. send a header ourselves), we must also set the Content-type header and terminate the headers, like below.
+*/
- /*` If we have no idea who they are, we'll send a form asking them for their name. The default `"Content-type"` header is `"text/plain"`, we'll change this to `"text/html"` so the user's browser will display the form. You can do this using `req.set_header("Content-type", "text/html")` or `rep<< header("Content-type", "text/html")`. Since writing with raw strings is error-prone, the shortcut below is available. */
- rep<< content_type("text/html")
- << "Hello there. What's your name?" "<p />"
- "<form method='POST'>"
- "<input type='text' name='user_name' />"
- "<input type='submit' />";
+ resp<< cookie("user_name", user_name)
+ << header("Date", "Tue, 15 Nov 1994 08:12:31 GMT")
+ << header("Content-type", "text/plain")
+ << header() // this terminates the headers
+ << "Hello there, " << user_name << ". You're new around here.";
+
+ resp.send(req);
+ }
- rep.send(req);
+/*`
+Now, if we have no idea who they are, we'll send a form asking them for their name. As the default `"Content-type"` header is `"text/plain"`, we'll change this to `"text/html"` so the user's browser will display the HTML form. You can do this using `req.set_header("Content-type", "text/html")` or `resp<< header("Content-type", "text/html")`. Since writing with raw strings is error-prone, the shortcut below is available.
+*/
+
+ resp<< content_type("text/html")
+ << header() // remember to end the headers
+ << "Hello there. What's your name?" "<p />"
+ "<form method='POST'>"
+ "<input type='text' name='user_name' />"
+ "<input type='submit' />";
+
+ resp.send(req);
+
+/*`
+And that's all we want to do for now, so we can close the program.
+*/
- /*` And that's all we want to do for now, so we can close the program. */
return 0;
}
//]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/accepting.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/accepting.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/accepting.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -7,14 +7,14 @@
[section:accepting Accepting Requests]
-A `basic_request_acceptor<>` is responsible for accepting requests. The following `typedefs` are provided for typical use:
+A [classref cgi::basic_request_acceptor `basic_request_acceptor<>`] is responsible for accepting requests. The following `typedefs` are provided for typical use:
``
-acgi_acceptor // aCGI
-fcgi_acceptor // FastCGI
-scgi_acceptor // SCGI
+acgi::acceptor // aCGI
+fcgi::acceptor // FastCGI
+scgi::acceptor // SCGI
``
-Note: `cgi_request` cannot be used with an acceptor, but an `acgi_request` will work fine: ie. only the first accept will succeed. A program written for SCGI or FastCGI will generally have one acceptor running in a loop.
+Note: `cgi::request` cannot be used with an acceptor, but an `acgi::request` will work fine: ie. only the first accept will succeed. A program written for SCGI or FastCGI will generally have an acceptor running in a loop.
Accepting requests is considered distinct to the [link __loading__ loading] stage for several reasons, the most significant of which is to allow for multiplexing protocols like FastCGI work with the other protocols.
@@ -23,16 +23,16 @@
[table
[[Function signature] [Purpose]]
[
- [`void accept(xcgi_request& empty_request)`]
+ [`void accept(xcgi::request& empty_request)`]
[Takes an empty request and blocks until a request is waiting to be handled. This will throw if the accept fails.]
]
[
[`boost::system::error_code&
- accept(xcgi_request& empty_request, boost::system::error_code& ec)`]
+ accept(xcgi::request& empty_request, boost::system::error_code& ec)`]
[Takes an empty request and blocks until a request is waiting to be handled. `ec` will be set such that `!ec == false` if the accept fails with an error code `ec`.]
]
[
- [`void async_accept(xcgi_request& empty_request, Handler handler)`]
+ [`void async_accept(xcgi::request& empty_request, Handler handler)`]
[Takes an empty request and asynchronously accepts a request. `handler` must be a model of __Handler__ and will be invoked when a request is accepted or an error occurs. The function always returns immediately.]
]
[
@@ -49,14 +49,16 @@
int main()
{
+ using namespace cgi::scgi; // for example
+
// create a ProtocolService
- cgi::scgi_service service;
+ service service;
// create an acceptor
- cgi::scgi_acceptor acceptor(service);
+ acceptor acceptor(service);
// make an empty request
- cgi::scgi_request req(service);
+ request req(service);
boost::system::error_code ec;
// accept a request
Added: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/cookies.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/cookies.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -0,0 +1,12 @@
+[/
+ / Copyright (c) 2007 Darren Garvey
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See accompanying
+ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ /]
+
+[section Cookies]
+
+
+
+[endsect]
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/loading.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/loading.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/loading.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -7,7 +7,7 @@
[section:loading Loading Requests]
-After a request has been accepted, it must also be 'loaded'. Before being loaded the request is in an undefined state and in general it is unsafe to call any `meta_*` function. For CGI, the request's constructor calls load implicitly (this is optional behaviour [footnote]), in most other situations, one of the following functions are used:
+After a request has been accepted, it should also be 'loaded'. Before being loaded the request is in an undefined state and it is unsafe to access any data associated with the request - although you may still read/write with the request. For CGI, the request's constructor calls load implicitly (this is optional behaviour [footnote You may pass `false` to the request's constructor. Note that the constructor options will become more explicit in the future.]), in most other situations, one of the following functions are used:
[table
[[Function signature] [Purpose]]
@@ -30,7 +30,7 @@
]
] [/table]
-What the call does is aquire the request environment data as necessary and parse the CGI __GET__ and `"HTTP_COOKIE"` variables. Also, if `parse_stdin == true` and the request method is POST, the CGI __POST__ data will be read and parsed.
+What the call does is acquire the request environment data as necessary and parse the CGI __GET__ and `"HTTP_COOKIE"` variables. Also, if `parse_stdin == true` and the request method is POST, the CGI __POST__ data will be read and parsed.
[h5 CGI example]
@@ -39,8 +39,10 @@
int main()
{
+ using namespace cgi::cgi;
+
// Delay loading the request data
- cgi::request req(false);
+ request req(false);
// ...
@@ -64,22 +66,25 @@
int main()
{
- // create a ProtocolService
- cgi::scgi_service service;
+ using namespace cgi::scgi;
+
+ // Create a ProtocolService
+ service service;
- // create an acceptor
- cgi::scgi_acceptor acceptor(service);
+ // Create an acceptor
+ acceptor acceptor(service);
- // make an empty request
- cgi::scgi_request req(service);
+ // Make an empty request
+ request req(service);
boost::system::error_code ec;
- // accept a request
+ // Accept a request
acceptor.accept(req, ec);
if (!ec)
{
- // a request was accepted ok
+ // A request was accepted ok, now parse all variables, including POST data
+ req.load(true);
}
return 0;
@@ -88,7 +93,6 @@
[h5 Asynchronous SCGI example]
-
``
#include <boost/cgi/scgi.hpp>
#include <boost/bind.hpp>
@@ -96,79 +100,83 @@
#include <boost/system/error_code.hpp>
#include <boost/enable_shared_from_this.hpp>
+using namespace cgi::scgi;
-void sub_main(scgi_request::pointer req)
+void sub_main(request::pointer req)
{
- // handle the request in here, as you would expect to
+ // handle the request in here, as you would any type of CGI request
}
-class scgi_server
- : public boost::enable_shared_from_this
+class Server
+ : public ``[@http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html `boost::enable_shared_from_this`]``
{
public:
- scgi_server(scgi_service& service)
- : service_(service)
- , acceptor_(service)
+ Server(service& _srv)
+ : service_(_srv)
+ , acceptor_(_srv)
{
async_accept();
}
void async_accept()
{
- scgi_request::pointer new_request(scgi_request::create(service_));
+ request::pointer new_request(request::create(service_));
acceptor_.async_accept(new_request
- , boost::bind(&scgi_server::handle_accept
+ , boost::bind(&Server::handle_accept
, shared_from_this()
, new_request
, boost::arg<1>));
}
- void handle_accept(scgi_request::pointer request, boost::system::error_code& ec)
+ void handle_accept(request::pointer request, boost::system::error_code& ec)
{
if (!ec)
{
// request was accepted ok; load it asynchronously (parsing POST data)
- request->async_load(true, boost::bind(&scgi_server::handle_load
+ request->async_load(true, boost::bind(&Server::handle_load
, shared_from_this()
, request
, boost::arg<1>));
}
}
- void handle_load(scgi_request::pointer request, boost::system::error_code& ec)
+ void handle_load(request::pointer request, boost::system::error_code& ec)
{
if (!ec)
{
- // the request loaded ok; handle it asynchronously and accept another request
+ // The request loaded ok;
+ // handle it asynchronously and accept another request.
service_.post(boost::bind(&sub_main, request));
async_accept();
}
}
private:
- scgi_service& service_;
- scgi_acceptor acceptor_;
+ service& service_;
+ acceptor acceptor_;
};
int main()
{
- // create a ProtocolService
- cgi::scgi_service service;
+ // Create a ProtocolService
+ service _service;
- // create a server to accept and load requests
- scgi_server server(service);
+ // Create a server to accept and load requests
+ server _server(_service);
- // create 5 background threads to run async operations *and* calls to sub_main
- // that are invoked through scgi_service::post(). Essentially this means the
- // program can handle at least 5 simultaneous requests: if asynchronous reads/
- // writes are used then more requests may be being handled at any one time
+ // Create 5 background threads to run async operations *and* calls to
+ // `sub_main` that are invoked through `service::post()`. Essentially this
+ // means the program can handle at least 5 simultaneous requests: if
+ // asynchronous reads/writes are used then more requests may be being handled
+ // at any one time.
boost::thread_group threads;
for(int i=5; i; i--)
{
- threads.create_thread(boost::bind(&scgi_service::run, service));
+ threads.create_thread(boost::bind(&service::run, _service));
}
- // make sure the program doesn't return until all threads are finished working
+ // Make sure the program doesn't return until all threads are finished
+ // working.
threads.join_all();
return 0;
Modified: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/requests.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/requests.qbk (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/requests.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -9,15 +9,15 @@
The class [classref cgi::basic_request `cgi::basic_request<>`] is the main entry point to the library. The following `typedef`s are provided for typical usage:
``
-cgi_request // CGI
-acgi_request // aCGI
-fcgi_request // FastCGI
-scgi_request // SCGI
+cgi::request // CGI -- note: this would be cgi::cgi::request fully-qualified
+acgi::request // aCGI
+fcgi::request // FastCGI
+scgi::request // SCGI
``
-The `cgi_request` is a bit different to the other types, in that it doesn't need to be constructed with a __ProtocolService__. This simplification makes it ideal for, and its use is detailed in, the '[link __scripting__ scripting]' quickstart. The other request types, however, have a distinct advantage in that they provide you with asynchronous functions.
+The `cgi::request` is a bit different to the other types, in that it doesn't need to be constructed with a __ProtocolService__. This simplification makes it ideal for, and its use is detailed in, the '[link __scripting__ scripting]' quickstart. The other request types, however, have a distinct advantage in that they provide you with asynchronous functions.
-[include:meta_data meta_variables.qbk]
+[include:data variables.qbk]
[/link ]
Added: sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/variables.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/src/user_guide/tutorial/variables.qbk 2007-08-22 22:43:19 EDT (Wed, 22 Aug 2007)
@@ -0,0 +1,176 @@
+[/
+ / Copyright (c) 2007 Darren Garvey
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See accompanying
+ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ /]
+
+[def __xss_footnote__ It is generally accepted that a CGI program should pay attention to where meta-data has come from (eg. [@http://www.google.com/search?q=XSS XSS]). In other words, since `meta_var` removes such distinctions, its use should be limited to places where the source of the variable doesn't matter. For example, a language toggle (like `"hl=en"`, as Google uses) could come from anywhere and doing so is not an issue.]
+
+
+[section:variables Using Request Variables]
+
+[warning
+A request [*must] be [link __loading__ loaded] before the request data can be accessed.
+]
+
+In all, there are twelve member functions of [classref cgi::basic_request `basic_request<>`] that provide access to the variables associated to that request. Five of those return a `cgi::map&` (all except `var_()`, which is simply a concatenation of all the other data) which you may use like a `std::map<std::string,std::string>` to search through the complete list of variables.
+
+[table Request variable accessor functions
+ [[Function signature] [Purpose]]
+ [
+ [`cgi::map& env_()`]
+ [Return a complete map of the meta-variables associated with the request.]
+ ]
+ [
+ [`std::string env_(const std::string&)`]
+ [Takes the name of the environment variable wanted and returns the value associated with it.]
+ ]
+ [
+ [`cgi::map& get_()`]
+ [Return a complete map of the GET variables associated with the request.]
+ ]
+ [
+ [`std::string get_(const std::string&)`]
+ [Takes the name of the __GET__ variable and returns the value associated with it (if any).]
+ ]
+ [
+ [`cgi::map& post_()`]
+ [Return a complete map of the POST variables associated with the request.]
+ ]
+ [
+ [`std::string post_(const std::string&, bool greedy = true)`]
+ [Takes the name of a __POST__ variable and returns the value associated with it (if any).
+
+ If `greedy == true` - which it is by default - then more data is read from the request if required until all of the POST data has been read.]
+ ]
+ [
+ [`cgi::map& form_()`]
+ [Return a complete map of the from variables associated with the request. These will either be the GET or POST variables, depending on whether the `request_method()` is `"GET"` or `"POST"` respectively.]
+ ]
+ [
+ [`std::string form_(const std::string&, bool greedy = true)`]
+ [Takes the name of either a __GET__ or __POST__ variable and returns the value associated with it (if any). Note that this will only search the type referred to by the environment variable `"REQUEST_METHOD"`, so it is generally safe to use.
+
+ If `greedy == true` - which it is by default - then more data is read from the request as required until all of the POST data has been read.]
+ ]
+ [
+ [`cgi::map& cookie_()`]
+ [Return a complete map of the cookie variables associated with a request.]
+ ]
+ [
+ [`std::string cookie_(const std::string& name)`]
+ [Takes the name of the cookie variable and returns the value associated with it (if any).]
+ ]
+ [
+ [`std::string var_(const std::string& name, bool greedy = true)`]
+ [Takes the name of [*any] meta-variable and returns the value associated with it (if any).[footnote __xss_footnote__]
+
+ If `greedy == true` - which it is by default - then more data is read from the request if required until either the requested variable is found or all of the POST data has been read, which ever comes first.]
+ ]
+]
+
+[h3 Example usage]
+
+``
+{
+// ...
+ cgi::request req;
+
+ cgi::map& get_vars = req.get_();
+ std::string user_id( get_vars["user_id"] );
+
+ if (!user_id.empty()) {
+ // user supplied a "user_id" in a GET request
+ // This method doesn't distinguish between an empty (set) variable
+ // and an unset variable.
+ }
+
+ cgi::map::const_iterator iter = get_vars.find("user_id");
+ if (iter = get_vars.end()) {
+ // "user_id" is unset
+ }else{
+ // "user_id" is empty
+ ``[@http://www.boost.org/libs/utility/assert.html BOOST_ASSERT]`` (iter->second == "");
+ }
+// ...
+}
+``
+
+Since looking up variables using raw strings can be error-prone, the `basic_request<>` class provides a safer way to reference the standard CGI environment variables. The table below lists them, and briefly explains their function.[footnote Reference information largely drafted from [@http://hoohoo.ncsa.uiuc.edu/cgi/env.html] and [@http://www.ietf.org/rfc/rfc3875 RFC3875].]
+
+[table Standard CGI Meta-variables
+ [[Function signature] [Purpose]]
+ [
+ [`std::string auth_type()`]
+ [If the server supports user authentication, and the script is protected, this is the protocol-specific authentication method used to validate the user.]
+ ]
+ [
+ [`std::string content_length()`]
+ [The size of the message-body attached to the request.]
+ ]
+ [
+ [`std::string content_type()`]
+ [The content type of data attached to the query, if any (ev. POST, PUT)]
+ ]
+ [
+ [`std::string gateway_interface()`]
+ [The revision of the CGI specification to which this server complies. Format: CGI/revision]
+ ]
+ [
+ [`std::string path_info()`]
+ [The extra path information, as given by the client. In other words, scripts can be accessed by their virtual pathname, followed by extra information at the end of this path. The extra information is sent as PATH_INFO. This information should be decoded by the server if it comes from a URL before it is passed to the CGI script.]
+ ]
+ [
+ [`std::string path_translated()`]
+ [The server provides a translated version of PATH_INFO, which takes the path and does any virtual-to-physical mapping to it.]
+ ]
+ [
+ [`std::string query_string()`]
+ [The information following the '?' in the URL. This is where the GET data is extracted from. Format: name1=value1&name2=value2... Any reserved characters are URL-encoded.]
+ ]
+ [
+ [`std::string remote_addr()`]
+ [The IP address of the remote host making the request. You should [*never] trust that this is accurate.]
+ ]
+ [
+ [`std::string remote_host()`]
+ [The hostname making the request.]
+ ]
+ [
+ [`std::string remote_ident()`]
+ [If the HTTP server supports RFC 931 identification, then this variable will be set to the remote user name retrieved from the server. Usage of this variable should be limited to logging only.]
+ ]
+ [
+ [`std::string remote_user()`]
+ [If the server supports user authentication, and the script is protected, this is the username they have authenticated as.]
+ ]
+ [
+ [`std::string request_method()`]
+ [The method with which the request was made. For HTTP, this is "GET", "HEAD", "POST", etc.]
+ ]
+ [
+ [`std::string script_name()`]
+ [A virtual path to the script being executed, used for self-referencing URLs.]
+ ]
+ [
+ [`std::string server_name()`]
+ [The server's hostname, DNS alias, or IP address as it would appear in self-referencing URLs.]
+ ]
+ [
+ [`std::string server_port()`]
+ [The port number to which the request was sent.]
+ ]
+ [
+ [`std::string server_protocol()`]
+ [The name and revision of the information protcol this request came in with. Format: protocol/revision.]
+ ]
+ [
+ [`std::string server_software()`]
+ [The name and version of the information server software answering the request (and running the gateway). Format: name/version.]
+ ]
+]
+
+[/ should this return a `std::pair<std::string, cgi::meta_type>` instead, where a `cgi::meta_type` is one of `get`, `post`, `env`, or `cookie`?]
+
+[endsect]
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk