|
Boost-Commit : |
From: lists.drrngrvy_at_[hidden]
Date: 2008-03-29 14:35:26
Author: drrngrvy
Date: 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
New Revision: 43934
URL: http://svn.boost.org/trac/boost/changeset/43934
Log:
Added documentation to the examples.
Added:
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/
- copied from r43866, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/
- copied from r43912, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp
- copied, changed from r43917, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/main.cpp
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/
- copied from r43917, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/
Removed:
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/servers/
Text files modified:
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp | 40 ++++++----
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp | 48 +++++++----
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp | 4 +
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp | 16 ++--
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 | 7 -
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/main.cpp | 15 ++-
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp | 6 +
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp | 71 +++++------------
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/Jamfile.v2 | 6
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp | 83 ++++----------------
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/Jamfile.v2 | 6
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/main.cpp | 154 +++++++++++++++------------------------
12 files changed, 186 insertions(+), 270 deletions(-)
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,13 @@
+
+[section Amortization]
+
+This example uses Google.cTemplate to move HTML out of the program and into HTML template files, which would be easily editable by anyone familiar with HTML.
+
+[import main.cpp]
+
+[acgi_amort]
+
+See the [@../../example/acgi/amortization/main.cpp full source listing].
+
+[endsect][/ echo]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
//
////////////////////////////////////////////////////////////////
//
+//[acgi_amort
+//
// Amortization Calculator
// -----------------------
//
@@ -116,7 +118,8 @@
// header - followed by a blank line - first though!).
std::string output;
tmpl->Expand(&output, &dict);
- std::cout<< output;
+ std::cout<< "Content-type: text/html\r\n\r\n"
+ << output;
}else
if (arg == "2")
{
@@ -124,32 +127,37 @@
// Should be expensive, but doesn't seem to impact performance hugely...
std::string output;
tmpl->Expand(&output, &dict);
- resp<< output;
+ resp<< content_type("text/html")
+ << output;
}else
-// if (arg == "3")
-// {
-// // Expand the string to a vector<const_buffer>, which should minimise any
-// // copying of data. This requires a modified version of Google.cTemplate, but
-// // doesn't seem to add anything to performance. Will have to check if there's a
-// // better way to do it.
-// std::string s;
-// std::vector<boost::asio::const_buffer> out;
-//
-// tmpl->Expand(&s, &out, &dict);
-// write(req.client(), out);
-// }else
+ // if (arg == "3")
+ // {
+ // // Expand the string to a vector<const_buffer>, which should minimise any
+ // // copying of data. This requires a modified version of Google.cTemplate, but
+ // // doesn't seem to add anything to performance. Will have to check if there's a
+ // // better way to do it.
+ // std::string s;
+ // std::vector<boost::asio::const_buffer> out;
+ //
+ // tmpl->Expand(&s, &out, &dict);
+ // write(req.client(), out);
+ // }else
if (arg == "4")
{
// Write the output directly to the request's client.
+ std::string headers("Content-type: text/html\r\n\r\n");
+ write(req.client(), buffer(headers));
std::string output;
tmpl->Expand(&output, &dict);
write(req.client(), buffer(output));
}else
- if (arg == "5")
+ if (arg == "5")
{
// An alternative to { arg == "1" }, which seems to be slightly faster.
std::string output;
tmpl->Expand(&output, &dict);
+ const char* headers = "Content-type: text/html\r\n\r\n";
+ std::cout.write(headers, strlen(headers));
std::cout.write(output.c_str(), output.size());
}else
{
@@ -160,7 +168,6 @@
int main()
{
try{
- std::cout<< "Content-type: text/html\r\n\r\n"; // just for debugging
service s;
request req(s);
req.load(true);
@@ -174,4 +181,5 @@
<< "ERROR!! BOOM!";
}
}
+//]
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section aCGI Examples]
+
+[include hello_world/doc.qbk]
+
+[include echo/doc.qbk]
+
+[include amortization/doc.qbk]
+
+[endsect][/ cgi_examples]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Echo]
+
+[import main.cpp]
+
+[acgi_echo]
+
+See the [@../../example/acgi/echo/main.cpp full source listing].
+
+[endsect][/ echo]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
//
////////////////////////////////////////////////////////////////
//
+//[acgi_echo
+//
// This example simply echoes all variables back to the user. ie.
// the environment and the parsed GET, POST and cookie variables.
// Note that GET and cookie variables come from the environment
@@ -15,15 +17,14 @@
#include <boost/cgi/acgi.hpp>
#include <fstream>
-//#include <google/template.h>
using namespace std;
using namespace boost::acgi;
// This function writes the title and map contents to the ostream in an
// HTML-encoded format (to make them easier on the eye).
-template<typename MapT, typename OStreamT>
-void show_map_contents(MapT& m, OStreamT& os, const std::string& title)
+template<typename OStream, Ttypename MapT>
+void show_map_contents(OStreamT& os, MapT& m, const std::string& title)
{
os<< "<h3>" << title << "</h3>";
if (m.empty()) os<< "NONE<br />";
@@ -52,7 +53,7 @@
{
response resp;
resp
- << content_type("text/plain")
+ << content_type("text/html")
<< "Error " << ec.value() << ": " << ec.message() << "<p />"
"--Original message follows--"
"<p />";
@@ -73,34 +74,43 @@
"</form><p />"
"boundary marker = " << req.boundary_marker() << "<p />";
- show_map_contents(req.GET(), resp, "GET Variables");
- show_map_contents(req.POST(), resp, "POST Variables");
- show_map_contents(req.cookie(), resp, "Cookie Variables");
- show_map_contents(req.env(), resp, "Environment Variables");
+ show_map_contents(resp, req[get_data], "GET Variables");
+ show_map_contents(resp, req[post_data], "POST Variables");
+ show_map_contents(resp, req[cookie_data], "Cookie Variables");
+ show_map_contents(resp, req[env_data], "Environment Variables");
- //resp<< content_type("text/html");
- resp.send(req.client());
+ return_(resp, req, 0); // All ok.
- }catch(boost::system::error_code& ec){
+ }
+ catch(boost::system::system_error& ec)
+ { // This is the type of error this library throws.
response resp;
- resp<< content_type("text/plain") << "Error " << ec.value() << ": "
- << ec.message();
- }catch(std::exception& e){
+ resp<< content_type("text/plain") << "Error " << ec.code() << ": "
+ << ec.what()
+ << http::internal_server_error; // note the status_code
+ return_(resp, req, 1);
+ }
+ catch(std::exception* e)
+ {
response resp;
- resp<< content_type("text/plain") << "Error: " << e.what();
+ resp<< content_type("text/plain") << "Error: " << e->what()
+ << http::internal_server_error;
return_(resp, req, 2);
}
+ // The request object will be destroyed before the next exception handlers
+ // are reached.
+
}catch(std::exception* e){
- std::cout
+ std::cerr
<< content_type("text/plain").content
<< "Exception: " << e->what();
- //resp.send(req.client());
return 3;
}catch(...){
- std::cout<< content_type("text/plain").content
+ std::cerr<< content_type("text/plain").content
<< "Unknown error.";
return 4;
}
- return 0;
}
+//]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Hello world]
+
+[import main.cpp]
+
+[acgi_hello_world]
+
+See the [@../../example/acgi/hello_world/main.cpp full source listing].
+
+[endsect][/ hello_world]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
//
////////////////////////////////////////////////////////////////
//
+//[acgi_hello_world
+//
// The simplest CGI program, outputs only "Hello there, universe."
//
@@ -30,3 +32,5 @@
// Leave this function, after sending the response and closing the request.
return_(resp, req, 0); // Note the underscore: returns "0" to the OS.
}
+//]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,9 @@
+
+[section CGI Examples]
+
+[include hello_world/doc.qbk]
+
+[include echo/doc.qbk]
+
+[endsect][/ cgi_examples]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Echo]
+
+[import main.cpp]
+
+[cgi_echo]
+
+See the [@../../example/cgi/echo/main.cpp full source listing].
+
+[endsect][/ echo]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,22 +7,22 @@
//
////////////////////////////////////////////////////////////////
//
+//[cgi_echo
+//
// This example simply echoes all variables back to the user. ie.
// the environment and the parsed GET, POST and cookie variables.
// Note that GET and cookie variables come from the environment
// variables QUERY_STRING and HTTP_COOKIE respectively.
//
-//[file
#include <boost/cgi/cgi.hpp>
-using namespace std;
using namespace boost::cgi;
// This function writes the title and map contents to the ostream in an
// HTML-encoded format (to make them easier on the eye).
-template<typename MapT, typename OStreamT>
-void show_map_contents(MapT& m, OStreamT& os, const std::string& title)
+template<typename OStreamT, typename MapT>
+void show_map_contents(OStreamT& os, MapT& m, const std::string& title)
{
os<< "<h3>" << title << "</h3>";
if (m.empty()) os<< "NONE<br />";
@@ -40,10 +40,10 @@
response resp;
- show_map_contents(req.env(), resp, "Environment Variables");
- show_map_contents(req.GET(), resp, "GET Variables");
- show_map_contents(req.POST(), resp, "POST Variables");
- show_map_contents(req.cookie(), resp, "Cookie Variables");
+ show_map_contents(resp, req[env_data], "Environment Variables");
+ show_map_contents(resp, req[get_data], "GET Variables");
+ show_map_contents(resp, req[post_data], "POST Variables");
+ show_map_contents(resp, req[cookie_data], "Cookie Variables");
// Note that this (and any other) HTTP header can go either before or after
// the response contents.
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -4,14 +4,13 @@
# (See accompanying file LICENSE_1_0.txt or copy
# at http://www.boost.org/LICENSE_1_0.txt)
-project boost.cgi.examples.acgi.hello_world
- ;
+project boost.cgi.examples.cgi.hello_world ;
-exe acgi_hello_world : main.cpp /boost/regex/ ;
+exe cgi_hello_world : main.cpp /boost/regex/ ;
# Our install rule (builds binaries and copies them to <location>)
install install
- : acgi_hello_world
+ : cgi_hello_world
: <location>$(cgi-bin)
;
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Hello world]
+
+[import main.cpp]
+
+[cgi_hello_world]
+
+See the [@../../example/cgi/hello_world/main.cpp full source listing].
+
+[endsect][/ hello_world]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/main.cpp
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,26 +7,27 @@
//
////////////////////////////////////////////////////////////////
//
+//[cgi_hello_world
+//
// The simplest CGI program, outputs only "Hello there, universe."
//
-#include <boost/cgi/acgi.hpp>
-#include <boost/cgi/return.hpp>
+#include <boost/cgi/cgi.hpp>
-using namespace std;
-using namespace boost::acgi;
+using namespace boost::cgi;
int main()
{
- service s; // This becomes useful with async operations.
- request req(s); // Our request (POST data won't be parsed yet).
+ request req; // Our request (POST data won't be parsed yet).
response resp; // A response object to make our lives easier.
// This is a minimal response. The content_type(...) may go before or after
// the response text.
- resp<< content_type("text/html")
+ resp<< content_type("text/plain")
<< "Hello there, universe.";
// Leave this function, after sending the response and closing the request.
return_(resp, req, 0); // Note the underscore: returns "0" to the OS.
}
+//]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,31 @@
+
+[section Examples]
+
+The examples can be built by going into their directory and typing `bjam`. If you have a server set up and wish to test the applications behind them, you can automatically copy them to your server's cgi-bin (or fcgi-bin or scgi-bin) one of two ways:
+
+[h4 Command Line]
+
+``$ bjam install --cgi-bin=/usr/lib/cgi-bin``
+
+Installs the CGI program (or set of programs) into `/usr/lib/cgi-bin`. If you want to install FastCGI examples from the `/libs/cgi/example/fcgi/` directory, for instance, type the above but replace `--cgi-bin=...` with `--fcgi-bin=...`.
+
+[h4 Environment Variables]
+
+Set the environment variable(s) `BOOST_CGI_BIN_PATH` (or `BOOST_FCGI_BIN_PATH`/`BOOST_SCGI_BIN_PATH`), then type:
+
+``$ bjam install``
+
+The example(s) will be installed into the relevant directory.
+
+[note
+ The command line option will override the environment variable, so you can use the environment variables for default installation.
+]
+
+[include cgi/doc.qbk]
+
+[include acgi/doc.qbk]
+
+[include fcgi/doc.qbk]
+
+[endsect]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,13 @@
+
+[section Amortization]
+
+This example uses Google.cTemplate to move HTML out of the program and into HTML template files, which would be easily editable by anyone familiar with HTML.
+
+[import main.cpp]
+
+[fcgi_amort]
+
+See the [@../../example/fcgi/amortization/main.cpp full source listing].
+
+[endsect][/ echo]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
//
////////////////////////////////////////////////////////////////
//
+//[fcgi_amort
+//
// Amortization Calculator
// -----------------------
//
@@ -185,7 +187,8 @@
try{
service s;
- acceptor a(s, true);
+ acceptor a(s, true); // The true means default-initialise.
+ // Unfortunately this only works on linux w. apache for now.
accept_requests(a);
@@ -199,4 +202,5 @@
std::cerr<< "ERROR!! BOOM!" << std::endl;
}
}
+//]
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,18 @@
+
+[section FastCGI Examples]
+
+[include echo/doc.qbk]
+
+[include amortization/doc.qbk]
+
+[section Servers]
+
+[include server1/doc.qbk]
+
+[include server2/doc.qbk]
+
+[include server3/doc.qbk]
+
+[endsect]
+
+[endsect]
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Echo]
+
+[import main.cpp]
+
+[fcgi_echo]
+
+See the [@../../example/fcgi/echo/main.cpp full source listing].
+
+[endsect][/ echo]
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,12 @@
+
+[section Server 1]
+
+This is a basic example demonstrating how using a `Server` can make your programs less dependent on a specific protocol.
+
+[import main.cpp]
+
+[fcgi_server1]
+
+[endsect][/ server_1]
+
+
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,14 @@
+
+[section Server 2]
+
+This is a very slight step up from the Server 1 example. It accepts new requests asynchronously, loads them synchronously and then handles them in a background thread while repeating the accept cycle.
+
+The asynchronous functions are run in ten background threads (see `server::run`).
+
+[import main.cpp]
+
+[fcgi_server2]
+
+[endsect][/ server_2]
+
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -34,13 +34,11 @@
using namespace std;
using namespace boost::fcgi;
-// This is a file to put internal logging info into
-#define LOG_FILE "/var/www/log/fcgi_server2.txt"
// This function writes the title and map contents to the ostream in an
// HTML-encoded format (to make them easier on the eye).
-template<typename Map, typename OStream>
-void format_map(Map& m, OStream& os, const std::string& title)
+template<typename OStream, typename Map>
+void format_map(OStream& os, Map& m, const std::string& title)
{
os<< "<h2>" << title << "</h2>";
if (m.empty()) os<< "NONE<br />";
@@ -51,32 +49,13 @@
}
}
-/// The handle_request member function is used to handle requests.
+/// Handle one request and return.
/**
- * A struct is used here just so a single log file can be shared between
- * requests. Note that access to the log file isn't synchronised (this doesn't
- * matter with this example).
+ * If it returns != 0 then an error has occurred. Sets ec to the error_code
+ * corresponding to the error.
*/
-struct request_handler
-{
- request_handler(const std::string& file_name)
- : log_(file_name.c_str())
- {
- if (!log_)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- throw std::runtime_error("Couldn't open log file");
- }
-
- log_<< boost::posix_time::second_clock::local_time() << endl;
- }
-
- int handle_request(fcgi::request& req, boost::system::error_code& ec)
+int handle_request(fcgi::request& req, boost::system::error_code& ec)
{
- std::ofstream log_(LOG_FILE, std::ios::app);
- //log_<< "Handling request" << endl
- // << "QUERY_STRING := " << req.query_string() << std::endl;
-
// Construct a `response` object (makes writing/sending responses easier).
response resp;
@@ -87,13 +66,9 @@
<< "Hello there, universe!<p />";
// Use the function defined above to show some of the request data.
- format_map(req.env(), resp, "Environment Variables");
- format_map(req.GET(), resp, "GET Variables");
- format_map(req.cookie(), resp, "Cookie Variables");
-
- // Response headers can be added at any time before send/flushing it:
- resp<< "<content-length == " << content_length(resp.content_length())
- << content_length(resp.content_length());
+ format_map(resp, req[env_data], "Environment Variables");
+ format_map(resp, req[get_data], "GET Variables");
+ format_map(resp, req[cookie_data], "Cookie Variables");
//log_<< "Handled request, handling another." << std::endl;
@@ -109,10 +84,6 @@
// Note: in this case `program_status == 0`.
}
-private:
- std::ofstream log_;
-};
-
/// The server is used to abstract away protocol-specific setup of requests.
/**
@@ -126,6 +97,8 @@
class server
{
public:
+ typedef fcgi::service service_type;
+ typedef fcgi::acceptor acceptor_type;
typedef fcgi::request request_type;
typedef boost::function<
int ( request_type&
@@ -138,7 +111,7 @@
, acceptor_(service_)
{}
- void run()
+ void run(int num_threads = 0)
{
// Create a new request (on the heap - uses boost::shared_ptr<>).
request_type::pointer new_request = request_type::create(service_);
@@ -146,7 +119,12 @@
requests_.insert(new_request);
start_accept(new_request);
- service_.run();
+ boost::thread_group tgroup;
+ for(int i(num_threads); i != 0; --i)
+ {
+ tgroup.create_thread(boost::bind(&service_type::run, &service_));
+ }
+ tgroup.join_all();
}
void start_accept(request_type::pointer& new_request)
@@ -196,21 +174,18 @@
private:
function_type handler_;
- fcgi::service service_;
- fcgi::acceptor acceptor_;
+ service_type service_;
+ acceptor_type acceptor_;
std::set<request_type::pointer> requests_;
};
int main()
try
{
- request_handler rh(LOG_FILE);
-
- server s(boost::bind(&request_handler::handle_request
- , &rh, _1, _2)
- );
+ server s(&handle_request);
- s.run();
+ // Run the server with 10 threads handling the asynchronous functions.
+ s.run(10);
return 0;
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/Jamfile.v2
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/Jamfile.v2 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,11 +1,11 @@
-project cgi.examples.fcgi.sync_server ;
+project cgi.examples.fcgi.server3 ;
-exe fcgi_server1 : main.cpp ;
+exe fcgi_server3 : main.cpp ;
install install
:
- fcgi_server1
+ fcgi_server3
:
<location>$(fcgi-bin)
;
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,12 @@
+
+[section Server 3]
+
+This is essentially the same as the Server 1 example, but it runs handles mutiple requests ['simultaneously] by calling `server::run` in a number of threads.
+
+[import main.cpp]
+
+[fcgi_server3]
+
+[endsect][/ server_3]
+
+
Copied: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp (from r43917, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/main.cpp)
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,4 +1,4 @@
-// -- server1/main.hpp --
+// -- server3/main.hpp --
//
// Copyright (c) Darren Garvey 2007.
// Distributed under the Boost Software License, Version 1.0.
@@ -7,7 +7,7 @@
//
////////////////////////////////////////////////////////////////
//
-//[fcgi_server1
+//[fcgi_server3
//
// This example simply echoes all variables back to the user. ie.
// the environment and the parsed GET, POST and cookie variables.
@@ -21,7 +21,7 @@
//
#include <fstream>
-#include <boost/bind.hpp>
+#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/program_options/environment_iterator.hpp>
@@ -30,66 +30,21 @@
using namespace std;
using namespace boost::fcgi;
-// This is a file to put internal logging info into
-#define LOG_FILE "/var/www/log/fcgi_server1.txt"
-
-// This function writes the title and map contents to the ostream in an
-// HTML-encoded format (to make them easier on the eye).
-template<typename Map, typename OStream>
-void format_map(Map& m, OStream& os, const std::string& title)
-{
- os<< "<h2>" << title << "</h2>";
- if (m.empty()) os<< "NONE<br />";
- for (typename Map::const_iterator i = m.begin(), end = m.end()
- ; i != end; ++i)
- {
- os<< "<b>" << i->first << "</b> = <i>" << i->second << "</i><br />";
- }
-}
-
-/// The handle_request member function is used to handle requests.
+/// Handle one request and return.
/**
- * A struct is used here just so a single log file can be shared between
- * requests. Note that access to the log file isn't synchronised (this doesn't
- * matter with this example).
+ * If it returns != 0 then an error has occurred. Sets ec to the error_code
+ * corresponding to the error.
*/
-struct request_handler
-{
- request_handler(const std::string& file_name)
- : log_(file_name.c_str())
- {
- if (!log_)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- throw std::runtime_error("Couldn't open log file");
- }
-
- log_<< boost::posix_time::second_clock::local_time() << endl;
- }
-
- int handle_request(fcgi::request& req, boost::system::error_code& ec)
+int handle_request(fcgi::request& req, boost::system::error_code& ec)
{
- std::ofstream log_(LOG_FILE, std::ios::app);
- //log_<< "Handling request" << endl
- // << "QUERY_STRING := " << req.query_string() << std::endl;
-
// Construct a `response` object (makes writing/sending responses easier).
response resp;
// Responses in CGI programs require at least a 'Content-type' header. The
// library provides helpers for several common headers:
- resp<< content_type("text/html")
+ resp<< content_type("text/plain")
// You can also stream text to a response object.
- << "Hello there, universe!<p />";
-
- // Use the function defined above to show some of the request data.
- format_map(req.env(), resp, "Environment Variables");
- format_map(req.GET(), resp, "GET Variables");
- format_map(req.cookie(), resp, "Cookie Variables");
-
- // Response headers can be added at any time before send/flushing it:
- resp<< "<content-length == " << content_length(resp.content_length())
- << content_length(resp.content_length());
+ << "Hello there, universe!";
//log_<< "Handled request, handling another." << std::endl;
@@ -105,11 +60,6 @@
// Note: in this case `program_status == 0`.
}
-private:
- std::ofstream log_;
-};
-
-
/// The server is used to abstract away protocol-specific setup of requests.
/**
* This server only works with FastCGI, but as you can see in the
@@ -175,13 +125,16 @@
int main()
try
{
- request_handler rh(LOG_FILE);
-
- server s(boost::bind(&request_handler::handle_request
- , &rh, _1, _2)
- );
+ server s(&handle_request);
- return s.run();
+ // Run the server in ten threads.
+ // => Handle ten requests simultaneously
+ boost::thread_group tgroup;
+ for(int i(10); i != 0; --i)
+ {
+ tgroup.create_thread(boost::bind(&server::run, &s));
+ }
+ tgroup.join_all();
}catch(boost::system::system_error& se){
cerr<< "[fcgi] System error: " << se.what() << endl;
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/Jamfile.v2
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/Jamfile.v2 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,11 +1,11 @@
-project cgi.examples.fcgi.server2 ;
+project cgi.examples.fcgi.server4 ;
-exe fcgi_server2 : main.cpp ;
+exe fcgi_server4 : main.cpp ;
install install
:
- fcgi_server2
+ fcgi_server4
:
<location>$(fcgi-bin)
;
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/main.cpp
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,4 +1,4 @@
-// -- server2/main.hpp --
+// -- server4/main.hpp --
//
// Copyright (c) Darren Garvey 2007.
// Distributed under the Boost Software License, Version 1.0.
@@ -7,7 +7,7 @@
//
////////////////////////////////////////////////////////////////
//
-//[fcgi_server2
+//[fcgi_server4
//
// This example simply echoes all variables back to the user. ie.
// the environment and the parsed GET, POST and cookie variables.
@@ -21,9 +21,6 @@
// Unlike in the server1 example, the server class in this example uses
// asynchronous functions, to increase throughput.
//
-//
-// **FIXME**
-// This is slower than the server1 example, which is stupid.
#include <fstream>
#include <boost/date_time/posix_time/posix_time.hpp>
@@ -34,85 +31,33 @@
using namespace std;
using namespace boost::fcgi;
-// This is a file to put internal logging info into
-#define LOG_FILE "/var/www/log/fcgi_server2.txt"
-
-// This function writes the title and map contents to the ostream in an
-// HTML-encoded format (to make them easier on the eye).
-template<typename Map, typename OStream>
-void format_map(Map& m, OStream& os, const std::string& title)
-{
- os<< "<h2>" << title << "</h2>";
- if (m.empty()) os<< "NONE<br />";
- for (typename Map::const_iterator i = m.begin(), end = m.end()
- ; i != end; ++i)
- {
- os<< "<b>" << i->first << "</b> = <i>" << i->second << "</i><br />";
- }
-}
-
-/// The handle_request member function is used to handle requests.
+/// Handle one request and return.
/**
- * A struct is used here just so a single log file can be shared between
- * requests. Note that access to the log file isn't synchronised (this doesn't
- * matter with this example).
+ * If it returns != 0 then an error has occurred. Sets ec to the error_code
+ * corresponding to the error.
*/
-struct request_handler
+int handle_request(fcgi::request& req, fcgi::response& resp
+ , boost::system::error_code& ec)
{
- request_handler(const std::string& file_name)
- : log_(file_name.c_str())
- {
- if (!log_)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- throw std::runtime_error("Couldn't open log file");
- }
-
- log_<< boost::posix_time::second_clock::local_time() << endl;
- }
-
- int handle_request(fcgi::request& req, boost::system::error_code& ec)
- {
- std::ofstream log_(LOG_FILE, std::ios::app);
- //log_<< "Handling request" << endl
- // << "QUERY_STRING := " << req.query_string() << std::endl;
-
- // Construct a `response` object (makes writing/sending responses easier).
- response resp;
-
- // Responses in CGI programs require at least a 'Content-type' header. The
- // library provides helpers for several common headers:
- resp<< content_type("text/html")
- // You can also stream text to a response object.
- << "Hello there, universe!<p />";
-
- // Use the function defined above to show some of the request data.
- format_map(req.env(), resp, "Environment Variables");
- format_map(req.GET(), resp, "GET Variables");
- format_map(req.cookie(), resp, "Cookie Variables");
-
- // Response headers can be added at any time before send/flushing it:
- resp<< "<content-length == " << content_length(resp.content_length())
- << content_length(resp.content_length());
-
- //log_<< "Handled request, handling another." << std::endl;
-
- // This funky macro finishes up:
- return_(resp, req, 0);
- // It is equivalent to the below, where the third argument is represented by
- // `program_status`:
- //
- // resp.send(req.client());
- // req.close(resp.status(), program_status);
- // return program_status;
- //
- // Note: in this case `program_status == 0`.
- }
-
-private:
- std::ofstream log_;
-};
+ // Responses in CGI programs require at least a 'Content-type' header. The
+ // library provides helpers for several common headers:
+ resp<< content_type("text/html")
+ // You can also stream text to a response object.
+ << "Hello there, universe!<p />";
+
+ // Use the function defined above to show some of the request data.
+ //format_map(req.env(), resp, "Environment Variables");
+ //format_map(req.GET(), resp, "GET Variables");
+ //format_map(req.cookie(), resp, "Cookie Variables");
+
+ // Response headers can be added at any time before send/flushing it:
+ resp<< "content-length == " << content_length(resp.content_length())
+ << content_length(resp.content_length());
+ //log_<< "Handled request, handling another." << std::endl;
+ //
+ return 0;
+}
/// The server is used to abstract away protocol-specific setup of requests.
/**
@@ -126,9 +71,12 @@
class server
{
public:
+ typedef fcgi::service service_type;
+ typedef fcgi::acceptor acceptor_type;
typedef fcgi::request request_type;
+ typedef fcgi::response response_type;
typedef boost::function<
- int ( request_type&
+ int ( request_type&, response_type&
, boost::system::error_code&)
> function_type;
@@ -138,7 +86,7 @@
, acceptor_(service_)
{}
- void run()
+ void run(int num_threads = 1)
{
// Create a new request (on the heap - uses boost::shared_ptr<>).
request_type::pointer new_request = request_type::create(service_);
@@ -146,7 +94,15 @@
requests_.insert(new_request);
start_accept(new_request);
- service_.run();
+
+ // Run all asynchronous functions in `num_threads` threads.
+ boost::thread_group tgroup;
+ for(int i(num_threads); i != 0; --i)
+ {
+ tgroup.create_thread(boost::bind(&service_type::run, &service_));
+ }
+ // Make sure we don't leave this function until all threads have exited.
+ tgroup.join_all();
}
void start_accept(request_type::pointer& new_request)
@@ -168,11 +124,16 @@
req->load(ec, true);
+ boost::shared_ptr<response_type> new_response(new response_type);
+ responses_.insert(new_response);
+
//req->async_load(boost::bind(&server::handle_request, this
// , req, boost::asio::placeholders::error)
// , true);
- service_.post(boost::bind(&server::handle_request, this, req, ec));
+ service_.post(boost::bind(&server::handle_request, this
+ , req, new_response, ec)
+ );
// Create a new request (on the heap - uses boost::shared_ptr<>).
request_type::pointer new_request = request_type::create(service_);
@@ -183,33 +144,34 @@
}
void handle_request(request_type::pointer req
+ , boost::shared_ptr<response_type> resp
, boost::system::error_code ec)
{
- handler_(*req, ec);
- if (ec)
+ int program_status( handler_(*req, *resp, ec) );
+ if (ec
+ || resp->send(*req, ec)
+ || req->close(resp->status(), program_status, ec))
{
- //std::cerr<< "Request handled, but ended in error: " << ec.message()
- // << std::endl;
+ std::cerr<< "Couldn't send response/close request." << std::endl;
}
- start_accept(req);
+ else
+ start_accept(req);
}
private:
function_type handler_;
- fcgi::service service_;
- fcgi::acceptor acceptor_;
+ service_type service_;
+ acceptor_type acceptor_;
std::set<request_type::pointer> requests_;
+ std::set<boost::shared_ptr<response_type> > responses_;
};
int main()
try
{
- request_handler rh(LOG_FILE);
-
- server s(boost::bind(&request_handler::handle_request
- , &rh, _1, _2)
- );
+ server s(&handle_request);
+ // Run the server.
s.run();
return 0;
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