|
Boost-Commit : |
From: lists.drrngrvy_at_[hidden]
Date: 2008-06-18 16:01:41
Author: drrngrvy
Date: 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
New Revision: 46489
URL: http://svn.boost.org/trac/boost/changeset/46489
Log:
* Made acgi/echo and fcgi/echo examples a bit nicer-looking.
* Added an overload of basic_request<>::load() that takes a parse_options
- so you can more carefully and clearly control what gets parsed.
Note: other versions of load() are deprecated and will eventually be removed.
* Changed common::status_type -> common::request_status.
* More work done in making fcgi/cgi internals common, so they can eventually be
abstracted out and more can be put into common::request_base<>.
Added:
sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp (contents, props changed)
sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_status.hpp (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/doc.qbk (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/src/library_sources.cpp (contents, props changed)
sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/parse_options.cpp (contents, props changed)
Removed:
sandbox/SOC/2007/cgi/trunk/boost/cgi/common/status_type.hpp
Text files modified:
sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp | 2
sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp | 1
sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp | 2
sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp | 125 +++++++++++++++++---------
sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/request_impl.hpp | 2
sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp | 36 +++----
sandbox/SOC/2007/cgi/trunk/boost/cgi/common/path_info.hpp | 24 ++--
sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp | 30 +++++
sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp | 34 ++++++-
sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_request_impl_base.hpp | 7
sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp | 182 +++++++++++++++++++++++++++------------
sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp | 1
sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/client.hpp | 45 +++++++--
sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request.hpp | 4
sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp | 89 +++++++++++++-----
sandbox/SOC/2007/cgi/trunk/boost/cgi/fwd/basic_request_fwd.hpp | 2
sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp | 143 ++++++++++++++++++++++++++----
sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp | 133 ++++++++++++++++------------
sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2 | 65 ++++++++------
sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/reference.qbk | 5
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk | 4
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp | 95 ++++++++++++++++----
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk | 4
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk | 4
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp | 155 +++++++++++++++++++++------------
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp | 19 ++-
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk | 12 +
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp | 7
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk | 22 +++
sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp | 12 +-
sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/Jamfile.v2 | 2
31 files changed, 862 insertions(+), 406 deletions(-)
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -21,7 +21,7 @@
typedef
common::basic_request<
- acgi::request_service, acgi::service
+ acgi::request_service, acgi::service
>
request;
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -11,7 +11,6 @@
#include "boost/cgi/acgi/service.hpp"
#include "boost/cgi/basic_client.hpp"
-#include "boost/cgi/common/status_type.hpp"
#include "boost/cgi/connections/async_stdio.hpp"
#include "boost/cgi/detail/cgi_request_impl_base.hpp"
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -14,7 +14,7 @@
#include "boost/cgi/common/map.hpp"
#include "boost/cgi/http/status_code.hpp"
#include "boost/cgi/common/role_type.hpp"
-#include "boost/cgi/common/status_type.hpp"
+#include "boost/cgi/common/request_status.hpp"
#include "boost/cgi/connections/tcp_socket.hpp"
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -31,7 +31,6 @@
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/http/status_code.hpp"
#include "boost/cgi/detail/throw_error.hpp"
-#include "boost/cgi/common/status_type.hpp"
#include "boost/cgi/common/source_enums.hpp"
#include "boost/cgi/fwd/basic_request_fwd.hpp"
#include "boost/cgi/common/request_service.hpp"
@@ -59,18 +58,20 @@
**/
template<typename RequestService
, typename ProtocolService
- , role_type Role
, typename Allocator>
class basic_request
- : public boost::mpl::if_c<
- is_async<typename RequestService::protocol_type>::type::value
+ : public boost::mpl::if_<
+ is_async<typename RequestService::protocol_type>
, basic_io_object<RequestService>
, detail::basic_sync_io_object<RequestService>
>::type
{
public:
- typedef basic_request<RequestService, ProtocolService
- , Role, Allocator > type;
+ typedef
+ basic_request<
+ RequestService, ProtocolService
+ , Allocator
+ > type;
typedef ::cgi::common::map map_type;
typedef RequestService service_type;
typedef typename service_type::protocol_type protocol_type;
@@ -80,6 +81,7 @@
typedef typename implementation_type::char_type char_type;
typedef typename implementation_type::string_type string_type;
typedef typename implementation_type::client_type client_type;
+ typedef typename implementation_type::buffer_type buffer_type;
// Throws
@@ -173,14 +175,38 @@
detail::throw_error(ec);
}
- // Error-code semantics
- boost::system::error_code&
- load(boost::system::error_code& ec, bool parse_stdin = false)
+ // Error-code semantics (**FIXME**)
+ boost::system::error_code
+ load(parse_options parse_opts, boost::system::error_code& ec)
+ {
+ return this->service.load(this->implementation, parse_opts, ec);
+ }
+
+ // Error-code semantics (**FIXME**)
+ boost::system::error_code
+ load(bool parse_stdin, boost::system::error_code& ec)
{
return this->service.load(this->implementation, parse_stdin, ec);
}
+ // Error-code semantics (**FIXME**)
+ boost::system::error_code
+ load(boost::system::error_code& ec, bool parse_stdin = false)
+ {
+ return this->service.load(this->implementation, parse_stdin, ec);
+ }
+ /// Get the buffer containing the POST data.
+ /**
+ * **FIXME**
+ * This actually returns the whole buffer on FastCGI at the moment, which
+ * contains the params too.
+ */
+ buffer_type& post_buffer()
+ {
+ return this->implementation.post_buffer_;
+ }
+
// **FIXME**
/// Asynchronously read/parse the request meta-data
/**
@@ -209,7 +235,7 @@
int close(common::http::status_code http_status = http::ok
, int program_status = 0)
{
- //BOOST_ASSERT( request_status_ != status_type::ended );
+ //BOOST_ASSERT( request_status_ != ended );
//this->service.set_status(this->implementation, http_status);
boost::system::error_code ec;
@@ -258,6 +284,23 @@
return this->service.client(this->implementation);
}
+ /// Read some data into the request, parsing if necessary.
+ void read_some()
+ {
+ boost::system::error_code ec;
+ this->service.read_some(this->implementation, ec);
+ detail::throw_error(ec);
+ }
+
+ /// Read some data into the request, parsing if necessary.
+ std::size_t
+ read_some(boost::system::error_code& ec)
+ {
+ return this->service.read_some(this->implementation, ec);
+ }
+
+ /// Read some data into the supplied buffer, parsing if necessary.
+ // **FIXME** (remove - use req.client().read_some() instead)
template<typename MutableBufferSequence>
void read_some(const MutableBufferSequence& buf)
{
@@ -266,10 +309,12 @@
detail::throw_error(ec);
}
+ /// Read some data into the supplied buffer, parsing if necessary.
+ // **FIXME** (remove - use req.client().read_some() instead)
template<typename MutableBufferSequence>
- boost::system::error_code
- read_some(const MutableBufferSequence& buf
- , boost::system::error_code& ec)
+ std::size_t
+ read_some(const MutableBufferSequence& buf
+ , boost::system::error_code& ec)
{
return this->service.read_some(this->implementation, buf, ec);
}
@@ -287,73 +332,59 @@
}
*/
- /// Search through environment variables for the matching name
- string_type var(string_type const& name, boost::system::error_code& ec)
- {
- return env_vars(this->implementation)[name.c_str()];
- }
-
- string_type var(string_type const& name)
- {
- boost::system::error_code ec;
- string_type ret (var(name, ec));
- detail::throw_error(ec);
- return ret;
- }
-
// [helper-functions for the basic CGI 1.1 meta-variables.
- string_type auth_type()
+ string_type& auth_type()
{ return env_("AUTH_TYPE"); }
- string_type content_length()
+ string_type& content_length()
{ return env_("CONTENT_LENGTH"); }
- string_type content_type()
+ string_type& content_type()
{ return env_("CONTENT_TYPE"); }
- string_type gateway_interface()
+ string_type& gateway_interface()
{ return env_("GATEWAY_INTERFACE"); }
- string_type path_info()
+ string_type& path_info()
{ return env_("PATH_INFO"); }
- string_type path_translated()
+ string_type& path_translated()
{ return env_("PATH_TRANSLATED"); }
- string_type query_string()
+ string_type& query_string()
{ return env_("QUERY_STRING"); }
- string_type remote_addr()
+ string_type& remote_addr()
{ return env_("REMOTE_ADDR"); }
- string_type remote_host()
+ string_type& remote_host()
{ return env_("REMOTE_HOST"); }
- string_type remote_ident()
+ string_type& remote_ident()
{ return env_("REMOTE_IDENT"); }
- string_type remote_user()
+ string_type& remote_user()
{ return env_("REMOTE_USER"); }
- string_type request_method()
+ string_type& request_method()
{ return env_("REQUEST_METHOD"); }
- string_type script_name()
+ string_type& script_name()
{ return env_("SCRIPT_NAME"); }
- string_type server_name()
+ string_type& server_name()
{ return env_("SERVER_NAME"); }
- string_type server_port()
+ string_type& server_port()
{ return env_("SERVER_PORT"); }
- string_type server_protocol()
+ string_type& server_protocol()
{ return env_("SERVER_PROTOCOL"); }
- string_type server_software()
+ string_type& server_software()
{ return env_("SERVER_SOFTWARE"); }
- string_type referer()
+ string_type& referer()
{ return env_("HTTP_REFERER"); }
// -- end helper-functions]
@@ -399,16 +430,20 @@
// environment.
// eg.
// string_type& val = req["some name"];
+
+ /// Get the value of the environment variable with name `n`.
string_type& operator[](string_type const& n)
{
return env_vars(this->implementation.vars_)[n.c_str()];
}
+ /// Get the value of the environment variable with name `n`.
string_type& operator[](const char* n)
{
return env_vars(this->implementation.vars_)[n];
}
+ /// Get the value of the environment variable with name `n`.
string_type& operator[](common::name const& n)
{
return env_vars(this->implementation.vars_)[n];
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/request_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/request_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/request_impl.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -20,7 +20,6 @@
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/http/status_code.hpp"
#include "boost/cgi/connections/stdio.hpp"
-#include "boost/cgi/common/status_type.hpp"
#include "boost/cgi/detail/cgi_request_impl_base.hpp"
// Make this ProtocolService-independent
@@ -69,3 +68,4 @@
} // namespace cgi
#endif // CGI_CGI_REQUEST_IMPL_HPP_INCLUDED__
+
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -29,37 +29,31 @@
namespace detail {
/// Destined for better things than an implementation detail (hopefully).
- template<typename RequestImplType>
class form_parser
{
public:
typedef
boost::function<
- std::size_t (
- const boost::asio::mutable_buffer&
- , boost::system::error_code& )
+ std::size_t (boost::system::error_code&)
>
callback_type;
+ typedef std::string string_type;
typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
typedef std::vector<char> buffer_type;
typedef ::cgi::common::map map_type;
- typedef RequestImplType implementation_type;
+/*
+ form_parser();
+ form_parser(callback_type const& callback);
+*/
+ form_parser(
+ buffer_type&, common::post_map&, string_type const&
+ , callback_type const&, std::size_t&, bool&);
- form_parser(implementation_type& impl);
- form_parser(implementation_type& impl, callback_type const& callback);
-
- mutable_buffers_type prepare(std::size_t size)
- {
- std::size_t bufsz(impl_.buffer_.size());
- impl_.buffer_.resize(bufsz + size);
- return boost::asio::buffer(&impl_.buffer_[bufsz], size);
- }
-
std::string buffer_string()
{
- return std::string(impl_.buffer_.begin() + offset_, impl_.buffer_.end());
+ return std::string(buffer_.begin() + offset_, buffer_.end());
}
boost::system::error_code
@@ -87,18 +81,22 @@
boost::system::error_code
parse_boundary_marker(boost::system::error_code& ec);
- private:
- implementation_type& impl_;
+ //private:
+ public:
+ string_type const& content_type_;
+ buffer_type& buffer_;
std::size_t& bytes_left_;
buffer_type::iterator pos_;
//bool& stdin_data_read_;
- std::size_t offset_;
+ common::post_map& data_map_;
std::string boundary_marker;
std::list<std::string> boundary_markers;
std::vector<common::form_part> form_parts_;
const callback_type callback_;
+ bool& stdin_parsed_;
+ std::size_t offset_;
};
} // namespace detail
Added: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_CGI_COMMON_PARSE_OPTIONS_HPP_INCLUDED_
+#define BOOST_CGI_COMMON_PARSE_OPTIONS_HPP_INCLUDED_
+
+namespace cgi {
+ namespace common {
+
+ enum parse_options
+ {
+ parse_none = 0 // you should *always* parse the environment!
+ , parse_env = 1
+ , parse_get = 2
+ , parse_post = 4
+ , parse_form = parse_get | parse_post
+ , parse_cookie = 8
+ , parse_all = parse_env | parse_form | parse_cookie
+ };
+
+ } // namespace common
+} // namespace cgi
+
+#endif // BOOST_CGI_COMMON_PARSE_OPTIONS_HPP_INCLUDED_
+
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/path_info.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/path_info.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/path_info.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -13,26 +13,26 @@
struct path_info
{
- typedef std::string string_type;
- typedef std::vector<string_type> vector_type;
- typedef vector_type::iterator iterator;
+ typedef std::string value_type;
+ typedef std::vector<value_type> vector_type;
+ typedef vector_type::iterator iterator;
- template<typename S, typename P, enum role_type R, typename A>
- path_info(basic_request<S,P,R,A>& request)
- : info(boost::algorithm::trim_copy_if(request["path_info"],
+ template<typename S, typename P, typename A>
+ path_info(basic_request<S,P,A> & request)
+ : value(boost::algorithm::trim_copy_if(request["path_info"],
boost::algorithm::is_any_of("/")))
{
- boost::algorithm::split(data, info, boost::algorithm::is_any_of("/"));
+ boost::algorithm::split(parts, value, boost::algorithm::is_any_of("/"));
}
- path_info(string_type const& str)
- : info(boost::algorithm::trim_copy_if(str, boost::algorithm::is_any_of("/")))
+ path_info(value_type const& str)
+ : value(boost::algorithm::trim_copy_if(str, boost::algorithm::is_any_of("/")))
{
- boost::algorithm::split(data, info, boost::algorithm::is_any_of("/"));
+ boost::algorithm::split(parts, value, boost::algorithm::is_any_of("/"));
}
- string_type info;
- vector_type data;
+ value_type value;
+ vector_type parts;
};
} // namespace common
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -33,6 +33,7 @@
class request_base
{
public:
+
/// Get the request ID of a FastCGI request, or 1.
template<typename ImplType>
int request_id(ImplType& impl)
@@ -40,7 +41,6 @@
return impl.client_.request_id_;
}
- protected:
// impl_base is the common base class for all request types'
// implementation_type and should be inherited by it.
struct impl_base
@@ -57,9 +57,33 @@
> var_map_type;
var_map_type vars_;
- buffer_type buffer_;
+ buffer_type post_buffer_;
+
+ mutable_buffers_type prepare(std::size_t size)
+ {
+ std::size_t bufsz(post_buffer_.size());
+ post_buffer_.resize(bufsz + size);
+ return boost::asio::buffer(&post_buffer_[bufsz], size);
+ }
};
-
+
+ /// Read some data into the internal buffer.
+ template<typename ImplType>
+ std::size_t
+ read_some(ImplType& impl, boost::system::error_code& ec)
+ {
+ return impl.client_.read_some(impl.prepare(64), ec);
+ }
+
+ /// Read some data from the client into the supplied buffer.
+ template<typename ImplType, typename MutableBufferSequence>
+ std::size_t
+ read_some(ImplType& impl, const MutableBufferSequence& buf
+ , boost::system::error_code& ec)
+ {
+ return impl.client_.read_some(buf,ec);
+ }
+
/// Read and parse the cgi GET meta variables
template<typename ImplType>
boost::system::error_code
Added: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_status.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_status.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -0,0 +1,29 @@
+// -- common/request_status.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// 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)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_COMMON_REQUEST_STATUS_HPP_INCLUDED__
+#define CGI_COMMON_REQUEST_STATUS_HPP_INCLUDED__
+
+namespace cgi {
+ namespace common {
+
+ enum request_status
+ { null
+ , unloaded
+ , activated
+ , loaded
+ , ok = loaded
+ , aborted
+ , closed
+ };
+
+ } // namespace common
+} // namespace cgi
+
+#endif // CGI_COMMON_REQUEST_STATUS_HPP_INCLUDED__
+
Deleted: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/status_type.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/status_type.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
+++ (empty file)
@@ -1,29 +0,0 @@
-// -- common/status_type.hpp --
-//
-// Copyright (c) Darren Garvey 2007.
-// 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)
-//
-////////////////////////////////////////////////////////////////
-#ifndef CGI_COMMON_STATUS_TYPE_HPP_INCLUDED__
-#define CGI_COMMON_STATUS_TYPE_HPP_INCLUDED__
-
-namespace cgi {
- namespace common {
-
- enum status_type
- { null
- , unloaded
- , activated
- , loaded
- , ok = loaded
- , aborted
- , closed
- };
-
- } // namespace common
-} // namespace cgi
-
-#endif // CGI_COMMON_STATUS_TYPE_HPP_INCLUDED__
-
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -13,10 +13,10 @@
#include <set>
///////////////////////////////////////////////////////////
#include <boost/asio.hpp>
+#include <boost/thread.hpp>
#include <boost/cstdint.hpp>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/thread.hpp>
///////////////////////////////////////////////////////////
#include "boost/cgi/error.hpp"
#include "boost/cgi/common/tags.hpp"
@@ -48,6 +48,9 @@
typedef boost::shared_ptr<
basic_connection<tags::shareable_tcp_socket> > pointer;
typedef boost::mutex mutex_type;
+ struct condition_type : public boost::condition_variable
+ { typedef boost::shared_ptr<boost::condition_variable> pointer; };
+ typedef boost::unique_lock<mutex_type> scoped_lock_type;
typedef boost::asio::ip::tcp::socket next_layer_type;
/** FastCGI specific stuff **/
@@ -57,14 +60,11 @@
typedef
detail::protocol_traits<fcgi_>::request_ptr request_ptr;
typedef std::map<boost::uint16_t, request_type*> request_map_type;
- typedef std::vector<request_type*> request_vector_type;
+ typedef std::vector<request_type*> request_vector_type;
/** End FastCGI stuff **/
// A wrapper to provide condition_type::pointer
- struct condition_type : public boost::condition_variable
- { typedef boost::shared_ptr<boost::condition_variable> pointer; };
-
basic_connection(io_service& ios)
: sock_(ios)
, mutex_()
@@ -91,6 +91,27 @@
sock_.close();
}
+ void lock()
+ {
+ scoped_lock_type(mutex_);
+ locked_ = true;
+ }
+
+ void unlock()
+ {
+ scoped_lock_type(mutex_);
+ locked_ = false;
+ condition_.notify_one();
+ }
+
+ void wait()
+ {
+ scoped_lock_type lock(mutex_);
+ if (locked_ = false)
+ return;
+ condition_.wait(lock);
+ }
+
static pointer create(io_service& ios)
{
return //static_cast<pointer>(
@@ -141,7 +162,7 @@
return sock_;
}
- mutex_type& mutex() { return mutex_; }
+ mutex_type& mutex() { return mutex_; }
condition_type& condition() { return condition_; }
boost::system::error_code
@@ -177,6 +198,7 @@
//}
private:
+ bool locked_;
next_layer_type sock_;
mutex_type mutex_;
condition_type condition_;
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_request_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_request_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_request_impl_base.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -21,7 +21,7 @@
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/http/status_code.hpp"
#include "boost/cgi/connections/stdio.hpp"
-#include "boost/cgi/common/status_type.hpp"
+#include "boost/cgi/common/request_status.hpp"
namespace cgi {
namespace detail {
@@ -60,10 +60,9 @@
bool stdin_parsed() { return stdin_parsed_; }
common::http::status_code& http_status() { return http_status_; }
- common::status_type& status() { return request_status_; }
+ common::request_status& status() { return request_status_; }
conn_ptr& connection() { return connection_; }
-
public:
//conn_ptr connection() { return connection_; }
@@ -76,7 +75,7 @@
protected:
common::http::status_code http_status_;
- common::status_type request_status_;
+ common::request_status request_status_;
conn_ptr connection_;
};
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -14,6 +14,7 @@
#include <string>
#include <cstdlib>
///////////////////////////////////////////////////////////
+#include <boost/bind.hpp>
#include <boost/assert.hpp>
#include <boost/regex.hpp>
#include <boost/tokenizer.hpp>
@@ -26,9 +27,10 @@
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/common/form_part.hpp"
#include "boost/cgi/detail/throw_error.hpp"
-#include "boost/cgi/common/status_type.hpp"
#include "boost/cgi/common/form_parser.hpp"
#include "boost/cgi/common/request_base.hpp"
+#include "boost/cgi/common/parse_options.hpp"
+#include "boost/cgi/common/request_status.hpp"
#include "boost/cgi/detail/extract_params.hpp"
#include "boost/cgi/detail/save_environment.hpp"
@@ -37,29 +39,19 @@
template<typename RequestImplType>
class cgi_service_impl_base
- : public common::request_base<cgi_service_impl_base<RequestImplType> >
+ : public common::request_base<cgi_service_impl_base<RequestImplType> >//, struct cgi_service_impl_base<RequestImplType>::implementation_type >
{
public:
- //typedef RequestImplType implementation_type;
- typedef ::cgi::common::map map_type;
-
- cgi_service_impl_base()
- {
- }
-
- template<typename T>
- cgi_service_impl_base(T&)
- {
- }
+ typedef cgi_service_impl_base<RequestImplType> self_type;
+ typedef common::request_base<self_type> base_type;
+ typedef ::cgi::common::map map_type;
struct implementation_type
: RequestImplType
- , common::request_base<
- cgi_service_impl_base<RequestImplType>
- >::impl_base
+ , base_type::impl_base
{
typedef typename RequestImplType::client_type client_type;
- typedef detail::form_parser<implementation_type> form_parser_type;
+ typedef detail::form_parser form_parser_type;
implementation_type()
: fp_(NULL)
@@ -74,6 +66,36 @@
boost::scoped_ptr<form_parser_type> fp_;
};
+ template<typename Service>
+ struct callback_functor
+ {
+ callback_functor(implementation_type& impl, Service* service)
+ : impl_(impl)
+ , service_(service)
+ {
+ }
+
+ std::size_t operator()(boost::system::error_code& ec)
+ {
+ return service_->read_some(impl_, ec);
+ }
+
+ private:
+ implementation_type& impl_;
+ Service* service_;
+ };
+
+ cgi_service_impl_base()
+ {
+ }
+
+ template<typename T>
+ cgi_service_impl_base(T&)
+ {
+ }
+
+ typedef implementation_type impl_type;
+
/// Return if the request is still open
/**
* For CGI, this always returns true. However, in the case that a
@@ -104,6 +126,46 @@
}
/// Synchronously read/parse the request meta-data
+ boost::system::error_code&
+ load(implementation_type& impl, common::parse_options parse_opts
+ , boost::system::error_code& ec)
+ {
+ if (parse_opts & common::parse_env)
+ {
+ if (read_env_vars(impl, ec)) // returns an error_code
+ return ec;
+ }
+
+ std::string const& cl = env_vars(impl.vars_)["CONTENT_LENGTH"];
+ impl.characters_left_ = cl.empty() ? 0 : boost::lexical_cast<std::size_t>(cl);
+ impl.client_.bytes_left() = impl.characters_left_;
+
+ std::string const& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
+
+ if (request_method == "GET" && parse_opts & common::parse_get)
+ {
+ parse_get_vars(impl, ec);
+ }
+ else
+ if (request_method == "POST" && parse_opts & common::parse_post)
+ {
+ parse_post_vars(impl, ec);
+ }
+
+ if (ec) return ec;
+
+ if (parse_opts & common::parse_cookie)
+ {
+ if (parse_cookie_vars(impl, ec)) // returns an error_code
+ return ec;
+ }
+
+ set_status(impl, common::loaded);
+
+ return ec;
+ }
+
+ /// Synchronously read/parse the request meta-data
/**
* @param parse_stdin if true then STDIN data is also read/parsed
*/
@@ -118,54 +180,23 @@
std::string const& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
if (request_method == "GET")
- this->parse_get_vars(impl, ec);
+ parse_get_vars(impl, ec);
else
if (request_method == "POST" && parse_stdin)
parse_post_vars(impl, ec);
if (ec) return ec;
- this->parse_cookie_vars(impl, ec);
+ parse_cookie_vars(impl, ec);
impl.status() = common::loaded;
//BOOST_ASSERT(impl.status() >= loaded);
return ec;
}
-/*
- // TODO: use `greedy`
- std::string
- form(implementation_type& impl, const std::string& name
- , boost::system::error_code& ec, bool greedy)
- {
- std::string rm(env(impl, "REQUEST_METHOD", ec));
- //BOOST_ASSERT(!ec && !rm.empty());
- if (rm == "GET")
- return GET(impl, name, ec);
- else
- if (rm == "POST")
- return POST(impl, name, ec);
- else
- // **FIXME** What about HEAD, PUT ???
- return "***BOOST_CGI_ERROR_INVALID_REQUEST_METHOD***";
- }
-
- // TODO: use `greedy`
- map_type&
- form(implementation_type& impl, boost::system::error_code& ec
- , bool greedy)
- {
- std::string rm(env(impl, "REQUEST_METHOD", ec));
- //BOOST_ASSERT(!ec && !rm.empty());
- if (rm == "GET")
- return GET(impl);
- else
- if (rm == "POST")
- return POST(impl, ec);
- }
-*/
+
role_type
- get_role(implementation_type& impl)
+ get_role(implementation_type& impl)
{
return responder;
}
@@ -173,18 +204,31 @@
/// Set the http status (this does nothing for aCGI)
void set_status(implementation_type& impl, common::http::status_code&)
{
+ // **FIXME**
+ }
+
+ /// Set the request status
+ void set_status(implementation_type& impl, common::request_status status)
+ {
+ impl.request_status_ = status;
}
- /// Read some data from the client.
- template<typename MutableBufferSequence>
std::size_t
- read_some(implementation_type& impl, const MutableBufferSequence& buf
- , boost::system::error_code& ec)
+ read_some(implementation_type& impl, boost::system::error_code& ec)
{
- return impl.client_.read_some(buf,ec);
+ return impl.client_.read_some(impl.prepare(64), ec);
}
protected:
+ /// Read the environment variables into an internal map.
+ template<typename RequestImpl>
+ boost::system::error_code
+ read_env_vars(RequestImpl& impl, boost::system::error_code& ec)
+ {
+ detail::save_environment(env_vars(impl.vars_));
+ return ec;
+ }
+
/// Read and parse the cgi POST meta variables (greedily)
template<typename RequestImpl>
boost::system::error_code
@@ -193,10 +237,32 @@
// Make sure this function hasn't already been called
//BOOST_ASSERT (!impl.stdin_parsed());
+ ;
+
impl.fp_.reset
(
new typename implementation_type::form_parser_type
- ( impl )
+ ( impl.post_buffer_
+ , post_vars(impl.vars_)
+ , env_vars(impl.vars_)["CONTENT_TYPE"]
+ , callback_functor<self_type>(impl, this)
+ //boost::bind(
+ //&self_type::read_some
+ //& typename ::cgi::common::request_base<
+ // ::cgi::cgi_service_impl_base<
+ // RequestImplType
+ // > >::read_some<
+ // typename ::cgi::cgi_service_impl_base<
+ // RequestImplType
+ // >::implementation_type
+ // >
+ //&cgi::common::base_type::read_some<typename self_type::implementation_type>
+ //, this
+ //, boost::ref(impl)
+ //)
+ , impl.client_.bytes_left_
+ , impl.stdin_parsed_
+ )
);
impl.fp_->parse(ec);
return ec;
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -275,6 +275,7 @@
{
request.clear();
}
+ //request.clear(); // **FIXME** (this should be cleverer)
// If we can reuse this request's connection, return.
if (request.client().keep_connection())
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/client.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/client.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -51,12 +51,7 @@
typedef ::cgi::common::map map_type;
typedef Protocol protocol_type;
typedef common::shareable_tcp_connection connection_type;
- //typedef detail::protocol_traits<
- // fcgi_
- //>::request_impl_type request_impl_type;
- //struct connection_type : shareable_tcp_connection
- //{ typedef boost::shared_ptr<connection_type> pointer; }
- typedef typename connection_type::pointer connection_ptr;
+ typedef typename connection_type::pointer connection_ptr;
typedef boost::array<
unsigned char
, fcgi::spec::header_length::value
@@ -185,31 +180,32 @@
/// Get a shared_ptr of the connection associated with the client.
connection_type::pointer&
- connection() { return connection_; }
+ connection() { return connection_; }
/// Write some data to the client.
template<typename ConstBufferSequence>
std::size_t
- write_some(const ConstBufferSequence& buf, boost::system::error_code& ec)
+ write_some(const ConstBufferSequence& buf, boost::system::error_code& ec)
{
typename ConstBufferSequence::const_iterator iter = buf.begin();
typename ConstBufferSequence::const_iterator end = buf.end();
std::vector<boost::asio::const_buffer> bufs;
- bufs.push_back(boost::asio::const_buffer());//header_buf_)); // space for header
+ bufs.push_back(boost::asio::buffer(out_header_));
int total_buffer_size(0);
for(; iter != end; ++iter)
{
boost::asio::const_buffer buffer(*iter);
int new_buf_size( boost::asio::buffer_size(buffer) );
+ // only write a maximum of 65535 bytes
if (total_buffer_size + new_buf_size
> fcgi::spec::max_packet_size::value)
break;
total_buffer_size += new_buf_size;
bufs.push_back(*iter);
}
- std::cerr<< "buffer size := " << total_buffer_size << std::endl;
+ std::cerr<< "Size of write buffer := " << total_buffer_size << std::endl;
//detail::make_header(out_header_, buf
out_header_[0] = static_cast<unsigned char>(1);
out_header_[1] = static_cast<unsigned char>(6);
@@ -220,7 +216,6 @@
out_header_[6] = static_cast<unsigned char>(0);
out_header_[7] = 0;
- bufs.front() = boost::asio::buffer(out_header_);
std::size_t bytes_transferred
= boost::asio::write(*connection_, bufs, boost::asio::transfer_all(), ec);
@@ -231,6 +226,29 @@
return bytes_transferred;
}
+ /// Read data into the supplied buffer.
+ /**
+ * Reads some data that, correctly checking and stripping FastCGI headers.
+ *
+ * Returns the number of bytes read and sets `ec` such that `ec` evaluates
+ * to `true` iff an error occured during the read operation.
+ *
+ * Notable errors:
+ * - `fcgi::error::data_for_another_request`
+ * - `fcgi::error::connection_locked`
+ *
+ * These must be dealt with by user code if they choose to read through the
+ * client (reading through the request is recommended).
+ */
+ template<typename MutableBufferSequence>
+ std::size_t
+ read_some(const MutableBufferSequence& buf, boost::system::error_code& ec)
+ {
+ std::size_t bytes_read(0);
+
+ return bytes_read;
+ }
+
/// Asynchronously write some data to the client.
template<typename ConstBufferSequence, typename Handler>
void async_write_some(const ConstBufferSequence& buf, Handler handler)
@@ -258,6 +276,11 @@
//int id() { return request_id_; }
+ std::size_t& bytes_left()
+ {
+ return bytes_left_;
+ }
+
public:
friend class fcgi_request_service;
boost::uint16_t request_id_;
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -19,8 +19,8 @@
// typedef for typical usage (FCGI)
typedef
- ::cgi::common::basic_request<
- fcgi_request_service, service
+ common::basic_request<
+ fcgi_request_service, service
>
request;
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -21,10 +21,11 @@
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/import/io_service.hpp"
#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/common/form_parser.hpp"
#include "boost/cgi/common/source_enums.hpp"
#include "boost/cgi/common/request_base.hpp"
#include "boost/cgi/detail/service_base.hpp"
-#include "boost/cgi/common/form_parser.hpp"
+#include "boost/cgi/common/parse_options.hpp"
namespace cgi {
namespace fcgi {
@@ -66,40 +67,53 @@
bool stdin_parsed_;
::cgi::common::http::status_code http_status_;
- common::status_type request_status_;
+ common::request_status request_status_;
fcgi::spec_detail::role_t request_role_;
+ std::size_t characters_left_;
bool all_done_;
- mutable_buffers_type prepare(std::size_t size)
- {
- using namespace std;
- std::size_t bufsz( buffer_.size() );
- //cerr<< "bufsz = " << bufsz << endl;
-
- // Reserve more space if it's needed.
- // (this could be safer, referencing this against CONTENT_LENGTH)
- //if ( (bufsz + size) >= buf_.capacity() )
- //{
- buffer_.resize(bufsz + size);
- //}
- return boost::asio::buffer(&buffer_[bufsz], size);
- }
-
-
/************** New stuff *****************/
header_buffer_type header_buf_;
boost::uint16_t id_;
- typedef detail::form_parser<implementation_type> form_parser_type;
+ typedef detail::form_parser form_parser_type;
boost::scoped_ptr<form_parser_type> fp_;
+ // Buffer to hold param records and filter data, etc.
+ buffer_type param_buffer_;
+
+ mutable_buffers_type prepare_misc(std::size_t size)
+ {
+ std::size_t bufsz(param_buffer_.size());
+ param_buffer_.resize(bufsz + size);
+ return boost::asio::buffer(¶m_buffer_[bufsz], size);
+ }
};
- typedef fcgi_request_service type;
- typedef ::cgi::fcgi::fcgi_request_service full_type;
- typedef type::implementation_type::protocol_type protocol_type;
- typedef type::implementation_type::request_type request_type;
+ typedef fcgi_request_service self_type;
+ typedef ::cgi::fcgi::fcgi_request_service full_type;
+ typedef self_type::implementation_type::protocol_type protocol_type;
+ typedef self_type::implementation_type::request_type request_type;
+
+ template<typename Service>
+ struct callback_functor
+ {
+ callback_functor(implementation_type& impl, Service* service)
+ : impl_(impl)
+ , service_(service)
+ {
+ }
+
+ std::size_t operator()(boost::system::error_code& ec)
+ {
+ return service_->read_some(impl_, ec);
+ }
+ private:
+ implementation_type& impl_;
+ Service* service_;
+ };
+
fcgi_request_service(::cgi::common::io_service& ios)
: detail::service_base<fcgi_request_service>(ios)
{
@@ -111,6 +125,7 @@
void construct(implementation_type& impl)
{
+ // **FIXME** move this to the client class
impl.client_.set_connection(//new implementation_type::connection_type(this->io_service()));
implementation_type::connection_type::create(this->io_service())
);
@@ -142,9 +157,11 @@
int close(implementation_type& impl, ::cgi::common::http::status_code& hsc
, int program_status);
+ /// Close the request.
int close(implementation_type& impl, ::cgi::common::http::status_code& hsc
, int program_status, boost::system::error_code& ec);
+ /// Clear all request data (object is then safe to remove).
void clear(implementation_type& impl);
/// Load the request to a point where it can be usefully used.
@@ -157,14 +174,21 @@
* packet for this request arrives from the server.
*
*/
- boost::system::error_code&
- load(implementation_type& impl, bool parse_stdin
+ boost::system::error_code
+ load(implementation_type& impl, bool parse_stdin
+ , boost::system::error_code& ec);
+
+ boost::system::error_code
+ load(implementation_type& impl, common::parse_options parse_opts
, boost::system::error_code& ec);
// **FIXME**
template<typename Handler>
void async_load(implementation_type& impl, bool parse_stdin, Handler handler);
+ /// Returns true if the request environment params have been read.
+ bool params_read(implementation_type& impl);
+
role_type get_role(implementation_type& impl)
{
return responder;
@@ -176,6 +200,8 @@
return impl.client_;
}
+ void set_status(implementation_type& impl, common::request_status status);
+
protected:
/// Read and parse the cgi POST meta variables (greedily)
boost::system::error_code&
@@ -189,8 +215,15 @@
/***************************************************************************/
public: // Reading stuff goes under here
+ /// Read some data from the client into the internal buffer.
+ std::size_t
+ read_some(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return read_some(impl, impl.prepare(64), ec);
+ }
+
// **FIXME**
- /// Read some data from the client.
+ /// Read some data from the client into the supplied buffer.
template<typename MutableBufferSequence>
std::size_t
read_some(implementation_type& impl, const MutableBufferSequence& buf
@@ -233,6 +266,10 @@
/// Parse the current header
boost::tribool parse_header(implementation_type& impl);
+ /// Read in the FastCGI (env) params
+ boost::system::error_code
+ read_env_vars(implementation_type& impl, boost::system::error_code& ec);
+
// Mammoth typedef corresponding to function signature of process_*
// functions.
typedef boost::system::error_code
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fwd/basic_request_fwd.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fwd/basic_request_fwd.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fwd/basic_request_fwd.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -9,7 +9,6 @@
#ifndef CGI_BASIC_REQUEST_FWD_HPP_INCLUDED__
#define CGI_BASIC_REQUEST_FWD_HPP_INCLUDED__
-#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/fwd/request_service_fwd.hpp"
#include "boost/cgi/fwd/basic_protocol_service_fwd.hpp"
@@ -18,7 +17,6 @@
template<typename RequestService
, typename ProtocolService
- , enum role_type Role = responder
, typename Allocator = std::allocator<char> >
class basic_request;
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -12,7 +12,6 @@
#include <boost/fusion/support.hpp>
#include <boost/system/error_code.hpp>
#include <boost/fusion/include/vector.hpp>
-#include <boost/mem_fn.hpp>
////////////////////////////////////////////////////////////////
#include "boost/cgi/common/map.hpp"
#include "boost/cgi/common/tags.hpp"
@@ -22,10 +21,10 @@
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/import/io_service.hpp"
#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/common/form_parser.hpp"
#include "boost/cgi/common/source_enums.hpp"
#include "boost/cgi/common/request_base.hpp"
#include "boost/cgi/detail/service_base.hpp"
-#include "boost/cgi/common/form_parser.hpp"
#include "boost/cgi/fcgi/request_service.hpp"
namespace cgi {
@@ -69,6 +68,7 @@
{
impl.all_done_ = true;
impl.client_.close(program_status);
+ impl.request_status_ = common::closed;
return program_status;
}
@@ -79,19 +79,23 @@
{
impl.all_done_ = true;
impl.client_.close(program_status, ec);
+ impl.request_status_ = common::closed;
return program_status;
}
BOOST_CGI_INLINE void
fcgi_request_service::clear(implementation_type& impl)
{
+ /*
BOOST_ASSERT
( impl.request_status_ < common::activated
&& impl.request_status_ > common::ok
&& "Are you trying to clear() a request without closing it?"
);
+ */
- impl.buffer_.clear();
+ impl.post_buffer_.clear();
+ impl.param_buffer_.clear();
common::get_vars(impl.vars_).clear();
common::post_vars(impl.vars_).clear();
common::cookie_vars(impl.vars_).clear();
@@ -117,7 +121,48 @@
*
*/
- BOOST_CGI_INLINE boost::system::error_code&
+ /// Synchronously read/parse the request meta-data
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::load(
+ implementation_type& impl, common::parse_options parse_opts
+ , boost::system::error_code& ec)
+ {
+ if (parse_opts & common::parse_env)
+ {
+ if (read_env_vars(impl, ec)) // returns an error_code
+ return ec;
+ }
+
+ std::string const& cl = env_vars(impl.vars_)["CONTENT_LENGTH"];
+ impl.characters_left_ = cl.empty() ? 0 : boost::lexical_cast<std::size_t>(cl);
+ impl.client_.bytes_left() = impl.characters_left_;
+
+ std::string const& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
+
+ if (request_method == "GET" && parse_opts & common::parse_get)
+ {
+ parse_get_vars(impl, ec);
+ }
+ else
+ if (request_method == "POST" && parse_opts & common::parse_post)
+ {
+ parse_post_vars(impl, ec);
+ }
+
+ if (ec) return ec;
+
+ if (parse_opts & common::parse_cookie)
+ {
+ if (parse_cookie_vars(impl, ec)) // returns an error_code
+ return ec;
+ }
+
+ set_status(impl, common::loaded);
+
+ return ec;
+ }
+
+ BOOST_CGI_INLINE boost::system::error_code
fcgi_request_service::load(
implementation_type& impl, bool parse_stdin
, boost::system::error_code& ec)
@@ -156,17 +201,17 @@
handle_other_request_header(impl);
}
- common::client_status completion_condition
- = parse_stdin ? common::stdin_read : common::params_read;
+ read_env_vars(impl, ec);
- while(!ec
- && impl.client_.status() < completion_condition
- && impl.request_status_ != common::loaded)
+ if (parse_stdin)
{
- //impl.client_.parse_packet(impl, ec);
- parse_packet(impl, ec);
+ while(!ec
+ && impl.client_.status() < common::stdin_read
+ && impl.request_status_ != common::loaded)
+ {
+ parse_packet(impl, ec);
+ }
}
-
const std::string& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
if (request_method == "GET")
if (parse_get_vars(impl, ec))
@@ -187,10 +232,23 @@
implementation_type& impl, bool parse_stdin, Handler handler)
{
this->io_service().post(
- detail::async_load_helper<type, Handler>(this, parse_stdin, handler)
+ detail::async_load_helper<self_type, Handler>(this, parse_stdin, handler)
);
}
+ BOOST_CGI_INLINE
+ bool fcgi_request_service::params_read(implementation_type& impl)
+ {
+ return impl.client_.status() >= common::params_read;
+ }
+
+ BOOST_CGI_INLINE
+ void fcgi_request_service::set_status(
+ implementation_type& impl, common::request_status status)
+ {
+ impl.request_status_ = status;
+ }
+
/// Read and parse the cgi POST meta variables (greedily)
BOOST_CGI_INLINE boost::system::error_code&
fcgi_request_service::parse_post_vars(
@@ -203,6 +261,7 @@
//# error "Not implemented"
// **FIXME** should use form_parser, when it's ready.
// Only works with url-encoded forms (ie. not with multipart forms)
+ /*
std::string name;
std::string str;
@@ -258,15 +317,20 @@
if( !name.empty() )
// **FIXME** have to have .c_str() ?
::cgi::common::post_vars(impl.vars_)[name.c_str()] = str;
+ */
- /*
impl.fp_.reset
(
new implementation_type::form_parser_type
- ( impl, boost::mem_fn(&fcgi_request_service::read_some<boost::asio::mutable_buffer>) )
+ ( impl.post_buffer_
+ , post_vars(impl.vars_)
+ , env_vars(impl.vars_)["CONTENT_TYPE"]
+ , callback_functor<self_type>(impl, this)
+ , impl.client_.bytes_left_
+ , impl.stdin_parsed_
+ )
);
impl.fp_->parse(ec);
- */
return ec;
}
@@ -303,7 +367,42 @@
//return bytes_read;
}
- /// Read a single header, buf do nothing with it.
+ /// Read in the FastCGI (env) params
+ // **FIXME**
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::read_env_vars(
+ implementation_type& impl, boost::system::error_code& ec)
+ {
+ while(!ec && !params_read(impl))
+ {
+ if (this->read_header(impl, ec))
+ return ec;
+
+ boost::tribool state = this->parse_header(impl);
+
+ if (state)
+ // the header has been handled and all is ok; continue.
+ return ec;
+ else
+ if (!state)
+ // The header is confusing; something's wrong. Abort.
+ return error::bad_header_type;
+
+ // else => (state == boost::indeterminate)
+
+ implementation_type::mutable_buffers_type buf
+ = impl.prepare_misc(fcgi::spec::get_length(impl.header_buf_));
+
+ if (this->read_body(impl, buf, ec))
+ return ec;
+
+ this->parse_body(impl, buf, ec);
+
+ } // while(!ec && !params_read(impl))
+ return ec;
+ }
+
+ /// Read a single header, but do nothing with it.
BOOST_CGI_INLINE boost::system::error_code
fcgi_request_service::read_header(
implementation_type& impl
@@ -528,11 +627,11 @@
template<typename MutableBuffersType> BOOST_CGI_INLINE
boost::system::error_code
fcgi_request_service::read_body(
- implementation_type& impl, const MutableBuffersType& buffer
+ implementation_type& impl, const MutableBuffersType& buf
, boost::system::error_code& ec)
{
std::size_t bytes_read
- = read(*impl.client_.connection_, buffer, boost::asio::transfer_all(), ec);
+ = read(*impl.client_.connection_, buf, boost::asio::transfer_all(), ec);
BOOST_ASSERT(bytes_read == fcgi::spec::get_length(impl.header_buf_)
&& "Couldn't read all of the record body.");
@@ -542,14 +641,14 @@
template<typename MutableBuffersType> BOOST_CGI_INLINE
boost::system::error_code
fcgi_request_service::parse_body(
- implementation_type& impl, const MutableBuffersType& buffer
+ implementation_type& impl, const MutableBuffersType& buf
, boost::system::error_code& ec)
{
return
(this->* proc_funcs[fcgi::spec::get_type(impl.header_buf_)])
(impl, fcgi::spec::get_request_id(impl.header_buf_)
- , boost::asio::buffer_cast<unsigned char*>(buffer)
- , boost::asio::buffer_size(buffer), ec);
+ , boost::asio::buffer_cast<unsigned char*>(buf)
+ , boost::asio::buffer_size(buf), ec);
}
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -13,50 +13,72 @@
#include "boost/cgi/basic_client.hpp"
#include "boost/cgi/detail/url_decode.hpp"
#include "boost/cgi/common/form_parser.hpp"
+#include "boost/cgi/common/source_enums.hpp"
namespace cgi {
namespace detail {
- template<typename T> BOOST_CGI_INLINE
- form_parser<T>::form_parser (
- implementation_type& impl
+/*
+ BOOST_CGI_INLINE
+ form_parser::form_parser (
)
- : impl_(impl)
+ : content_type_(env_vars(impl.vars_)["CONTENT_TYPE"])
+ , buffer_(impl.buffer_)
, bytes_left_(impl.client_.bytes_left_)
//, stdin_data_read_(impl.stdin_data_read_)
, offset_(0)
- , callback_(NULL)
+ , data_map_(post_vars(impl.vars_))
+ , callback_()
{
}
- template<typename T> BOOST_CGI_INLINE
- form_parser<T>::form_parser (
- implementation_type& impl
+ BOOST_CGI_INLINE
+ form_parser::form_parser (
, callback_type const& callback
)
- : impl_(impl)
+ : content_type_(env_vars(impl.vars_)["CONTENT_TYPE"])
+ , buffer_(impl.buffer_)
, bytes_left_(impl.client_.bytes_left_)
//, stdin_data_read_(impl.stdin_data_read_)
, offset_(0)
+ , data_map_(post_vars(impl.vars_))
, callback_(callback)
{
}
+*/
- template<typename T> BOOST_CGI_INLINE
- boost::system::error_code
- form_parser<T>::parse(boost::system::error_code& ec)
+ BOOST_CGI_INLINE
+ form_parser::form_parser (
+ buffer_type& buf
+ , common::post_map& data_map
+ , form_parser::string_type const& ct
+ , callback_type const& callback
+ , std::size_t& bytes_left
+ , bool& stdin_parsed
+ )
+ : content_type_(ct)//env_vars(impl.vars_)["CONTENT_TYPE"])
+ , buffer_(buf)
+ , bytes_left_(bytes_left)
+ , data_map_(data_map)
+ , callback_(callback)
+ , stdin_parsed_(stdin_parsed)
+ , offset_(0)
{
- std::string content_type (env_vars(impl_.vars_)["CONTENT_TYPE"]);
+ }
- BOOST_ASSERT(!content_type.empty());
+ BOOST_CGI_INLINE
+ boost::system::error_code
+ form_parser::parse(boost::system::error_code& ec)
+ {
+ BOOST_ASSERT(!content_type_.empty());
- if (boost::algorithm::ifind_first(content_type,
+ if (boost::algorithm::ifind_first(content_type_,
"application/x-www-form-urlencoded"))
{
parse_url_encoded_form(ec);
}
else
- if (boost::algorithm::ifind_first(content_type,
+ if (boost::algorithm::ifind_first(content_type_,
"multipart/form-data"))
{
parse_multipart_form(ec);
@@ -67,9 +89,9 @@
return ec;
}
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::parse_url_encoded_form(boost::system::error_code& ec)
+ form_parser::parse_url_encoded_form(boost::system::error_code& ec)
{
std::string name;
std::string str;
@@ -114,7 +136,7 @@
break;
case '&': // we now have the name/value pair, so save it
// **FIXME** have to have .c_str() ?
- post_vars(impl_.vars_)[name.c_str()] = str;
+ data_map_[name.c_str()] = str;
str.clear();
name.clear();
break;
@@ -125,15 +147,15 @@
// save the last param (it won't have a trailing &)
if( !name.empty() )
// **FIXME** have to have .c_str() ?
- post_vars(impl_.vars_)[name.c_str()] = str;
+ data_map_[name.c_str()] = str;
return ec;
}
/// Parse a multipart form.
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::parse_multipart_form(boost::system::error_code& ec)
+ form_parser::parse_multipart_form(boost::system::error_code& ec)
{
parse_boundary_marker(ec);
@@ -145,16 +167,16 @@
do {
parse_form_part(ec);
}while( //!impl_.stdin_parsed_
- impl_.client_.bytes_left_ // != 0
+ bytes_left_ // != 0
);//&& ec != boost::asio::error::eof );
return ec;
}
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::parse_form_part(boost::system::error_code& ec)
+ form_parser::parse_form_part(boost::system::error_code& ec)
{
if (!parse_form_part_meta_data(ec)
&& !parse_form_part_data(ec))
@@ -163,9 +185,9 @@
return ec;
}
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::parse_form_part_data(boost::system::error_code& ec)
+ form_parser::parse_form_part_data(boost::system::error_code& ec)
{
std::string regex("^(.*?)" // the data
"\\x0D\\x0A" // CR LF
@@ -195,8 +217,8 @@
std::size_t offset = offset_;
//int runs = 0;
- buffer_iter begin(impl_.buffer_.begin() + offset);
- buffer_iter end(impl_.buffer_.end());
+ buffer_iter begin(buffer_.begin() + offset);
+ buffer_iter end(buffer_.end());
for(;;)
{
@@ -214,7 +236,7 @@
// = boost::range_iterator<;
= std::make_pair(matches[1].first, matches[1].second);
// **FIXME**
- post_vars(impl_.vars_)[form_parts_.back().name.c_str()] = matches[1];
+ data_map_[form_parts_.back().name.c_str()] = matches[1];
//std::ofstream of("c:/cc/log/post_vars.log");
//of<< "var == " << matches[1] << std::endl;
offset_ = offset + matches[0].length();
@@ -222,7 +244,7 @@
if (matches[3].matched)
{
- impl_.client_.bytes_left_ = 0; // stop reading completely.
+ bytes_left_ = 0; // stop reading completely.
//impl_.stdin_parsed_ = true;
}
return ec;
@@ -230,17 +252,17 @@
else
{
std::size_t bytes_read
- = //callback_(prepare(64), ec);
- impl_.client_.read_some(prepare(64), ec);
+ = callback_(ec);
+ //impl_.client_.read_some(prepare(64), ec);
- if (bytes_read == 0 && impl_.client_.bytes_left_ == 0) // **FIXME**
+ if (bytes_read == 0 && bytes_left_ == 0) // **FIXME**
{
//stdin_data_read_ = true;
return ec;
}
- begin = impl_.buffer_.begin() + offset;
- end = impl_.buffer_.end();
+ begin = buffer_.begin() + offset;
+ end = buffer_.end();
if (ec)
return ec;
@@ -251,9 +273,9 @@
return ec;
}
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::parse_form_part_meta_data(boost::system::error_code& ec)
+ form_parser::parse_form_part_meta_data(boost::system::error_code& ec)
{
// Oh dear this is ugly. The move to Boost.Spirit will have to be sooner than planned.
// (it's a nested, recursive pattern, which regexes don't suit, apparently)
@@ -307,19 +329,19 @@
boost::match_results<buffer_iter> matches;
std::size_t offset = offset_;
- pos_ = impl_.buffer_.begin();
+ pos_ = buffer_.begin();
int runs = 0;
std::size_t bytes_read = 0;
for(;;)
{
- buffer_iter begin(impl_.buffer_.begin() + offset);
- buffer_iter end(impl_.buffer_.end());
+ buffer_iter begin(buffer_.begin() + offset);
+ buffer_iter end(buffer_.end());
if (!boost::regex_search(begin, end, matches, re
, boost::match_default | boost::match_partial))
{
- impl_.stdin_parsed_ = true;
+ stdin_parsed_ = true;
return ec;
}
if (matches[0].matched)
@@ -358,8 +380,7 @@
}else{
bytes_read
- = //callback_(prepare(64), ec);
- impl_.client_.read_some(prepare(64), ec);
+ = callback_(ec);
if (ec)
return ec;
if (++runs > 40)
@@ -373,9 +394,9 @@
return ec;
}
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::move_to_start_of_first_part(boost::system::error_code& ec)
+ form_parser::move_to_start_of_first_part(boost::system::error_code& ec)
{
boost::regex re("((?:.*)?" // optional leading characters
//"(?:\\x0D\\x0A)|^" // start of line
@@ -399,26 +420,25 @@
for(;;)
{
bytes_read
- = //callback_(prepare(32), ec);
- impl_.client_.read_some(prepare(32), ec);
+ = callback_(ec);
if (ec || (bytes_read == 0))
return ec;
- buffer_iter begin(impl_.buffer_.begin());// + offset);
- buffer_iter end(impl_.buffer_.end());
+ buffer_iter begin(buffer_.begin());// + offset);
+ buffer_iter end(buffer_.end());
if (!boost::regex_search(begin, end //impl.buffer_.begin(), impl.buffer_.end()
, matches, re, boost::match_default | boost::match_partial))
{
- offset = impl_.buffer_.size();
+ offset = buffer_.size();
continue;
}
else
{
if (matches[2].matched)
{
- impl_.buffer_.erase(impl_.buffer_.begin(), matches[0].second);
+ buffer_.erase(buffer_.begin(), matches[0].second);
offset_ = 0;
- pos_ = impl_.buffer_.begin();
+ pos_ = buffer_.begin();
return ec;
}
else
@@ -433,12 +453,10 @@
return ec;
}
- template<typename T> BOOST_CGI_INLINE
+ BOOST_CGI_INLINE
boost::system::error_code
- form_parser<T>::parse_boundary_marker(boost::system::error_code& ec)
+ form_parser::parse_boundary_marker(boost::system::error_code& ec)
{
- // get the meta-data appended to the content_type
- std::string content_type_(env_vars(impl_.vars_)["CONTENT_TYPE"]);
//BOOST_ASSERT(!content_type.empty());
boost::regex re("; ?boundary=\"?([^\"\n\r]+)\"?");
@@ -449,6 +467,7 @@
boundary_marker = match_results[1].str();
// New boundary markers are added to the front of the list.
boundary_markers.push_front(match_results[1].str());
+ std::cerr<< "boundary marker := " << boundary_marker << std::endl;
return ec;
}
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -11,26 +11,39 @@
import doxygen ;
# compile the doxygen sources here
-doxygen cgi_dox
+doxygen autodoc
:
# [ glob-tree ../../../boost/cgi/*.hpp : .svn ]
# [ glob-tree ../../../boost/libs/cgi/src/*.cpp : .svn ]
- [ glob ../../../boost/cgi/*.hpp ]
- [ glob ../../../boost/cgi/fcgi*.hpp ]
- [ glob ../../../boost/cgi/acgi*.hpp ]
- [ glob ../../../boost/cgi/cgi*.hpp ]
-# [ glob ../../../boost/cgi/gateway_impl/*.hpp ]
-# [ glob ../../../boost/cgi/gateway_service/*.hpp ]
- [ glob ../../../boost/cgi/http/*.hpp ]
-# [ glob ../../../boost/cgi/connections/*.hpp ]
-# [ glob ../../../boost/cgi/request_impl/*.hpp ]
-# [ glob ../../../boost/cgi/request_service/*.hpp ]
+ [ glob $(top)/boost/cgi/*.hpp ]
+ $(top)/boost/cgi/fcgi/client.hpp
+ $(top)/boost/cgi/fcgi/service.hpp
+ $(top)/boost/cgi/fcgi/acceptor.hpp
+ $(top)/boost/cgi/fcgi/request.hpp
+ $(top)/boost/cgi/acgi/service.hpp
+ $(top)/boost/cgi/acgi/acceptor.hpp
+ $(top)/boost/cgi/acgi/request.hpp
+ $(top)/boost/cgi/cgi/service.hpp
+ $(top)/boost/cgi/cgi/request.hpp
+ $(top)/boost/cgi/http/status_code.hpp
+ #[ glob $(top)/boost/cgi/acgi/*.hpp ]
+ #[ glob $(top)/boost/cgi/cgi/*.hpp ]
+ [ glob $(top)/boost/cgi/common/*.hpp ]
+
+ [ glob ../../../boost/cgi/connections/*.hpp ]
:
-# <doxygen:param>HIDE_UNDOC_MEMBERS=NO
+ #<doxygen.processor>doxproc
+ #<doxygen.doxproc.index>yes
+ #<doxygen.doxproc.title>"Developer Reference"
+ #<doxygen.doxproc.id>"developer_reference"
+
+ <doxygen:param>HIDE_UNDOC_MEMBERS=NO
<doxygen:param>EXTRACT_PRIVATE=NO
-# #<doxygen:param>EXTRACT_ALL=YES
+ <doxygen:param>EXTRACT_ALL=YES
<doxygen:param>SEARCH_INCLUDES=YES
+ <doxygen:param>GENERATE_TREEVIEW=ALL
+ <doxygen:param>TYPEDEF_HIDES_STRUCT=YES
# <doxygen:param>INCLUDE_PATH=$(BOOST_ROOT)
;
@@ -39,31 +52,27 @@
boostbook standalone
:
cgi_xml
- cgi_dox
+ autodoc
+ #cgi_dox
:
- <doxygen.processor>doxproc
- <doxygen.doxproc.index>no
- <doxygen.doxproc.title>"Developer Reference"
- <doxygen.doxproc.id>"developer_reference"
-
- <xsl:param>project.root=../../../..
- <xsl:param>boost.libraries=/usr/local/src/boost/trunk/libs/libraries.htm
- <xsl:param>boost.images=http://beta.boost.org/images
+ #<xsl:param>project.root=../../../..
+ #<xsl:param>boost.libraries=/usr/local/src/boost/trunk/libs/libraries.htm
+ #<xsl:param>boost.images=http://beta.boost.org/images
# the depth (of sub-pages) the TOC shows
- <xsl:param>toc.max.depth=1
+ #<xsl:param>toc.max.depth=1
# Path to the stylesheet
- <xsl:param>html.stylesheet=../../../../../../boost/trunk/doc/html/boostbook.css
+ #<xsl:param>html.stylesheet=../../../../../../boost/trunk/doc/html/boostbook.css
#
- <xsl:param>toc.section.depth=2
+ #<xsl:param>toc.section.depth=2
# How far down we go with TOC's
- <xsl:param>generate.section.toc.level=10
+ #<xsl:param>generate.section.toc.level=10
# how many sections are on the first page
- <xsl:param>chunk.first.sections=1
+ #<xsl:param>chunk.first.sections=1
# To chunk (together) or not to chunk (divide)
- <xsl:param>chunk.section.depth=2 # chunk
+ #<xsl:param>chunk.section.depth=2 # chunk
;
#install html
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/reference.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/reference.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/reference.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -7,9 +7,9 @@
[section:ref Reference]
-[xinclude ../cgi_dox.xml]
+[xinclude ../autodoc.xml]
-[h2 Quick Reference]
+[section Quick Reference]
Reference coming...
@@ -59,6 +59,7 @@
* data()
* content_length()
+[endsect] [/ quick_reference]
[endsect] [/ ref]
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -3,6 +3,10 @@
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.
+[note
+ You need to download and install [@http://code.google.com/p/google-ctemplate Google's cTemplate library] and you may have to modify Jamfile.v2 to point to your compiled ctemplate library (see the `lib ctemplate ...` lines).
+]
+
[import main.cpp]
[acgi_amort]
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-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -17,25 +17,57 @@
#include <fstream>
#include <cstdio>
+#include <vector>
///////////////////////////////////////////////////////////
#include "boost/cgi/acgi.hpp"
using namespace std;
using namespace boost::acgi;
+// The styling information for the page.
+static const char* gCSS_text =
+"body { padding: 0; margin: 3%; border-color: #efe; }"
+".var_map_title"
+ "{ font-weight: bold; font-size: large; }"
+".var_map"
+ "{ border: 1px dotted; padding: 2px 3px 2px 3px; margin-bottom: 3%; }"
+".var_pair"
+ "{ border-top: 1px dotted; overflow: auto; padding: 0; margin: 0; }"
+".var_name"
+ "{ position: relative; float: left; width: 30%; font-weight: bold; }"
+".var_value"
+ "{ position: relative; float: left; width: 65%; left: 1%;"
+ " border-left: 1px solid; padding: 0 5px 0 5px;"
+ " overflow: auto; white-space: pre; }"
+;
+
+//
// 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 OStreamT, typename MapT>
-void show_map_contents(OStreamT& os, MapT& m, const std::string& title)
+void format_map(OStreamT& os, MapT& m, const std::string& title)
{
- os<< "<h3>" << title << "</h3>";
+ os<< "<div class=\"var_map\">"
+ "<div class=\"var_map_title\">"
+ << title
+ << "</div>";
+
if (m.empty())
- os<< "NONE<br />";
+ os<< "<div class=\"var_pair\">EMPTY</div>";
else
for (typename MapT::const_iterator i = m.begin(); i != m.end(); ++i)
{
- os<< "<b>" << i->first << "</b> = <i>" << i->second << "</i><br />";
+ os<< "<div class=\"var_pair\">"
+ "<div class=\"var_name\">"
+ << i->first
+ << "</div>"
+ "<div class=\"var_value\">"
+ << i->second
+ << "</div>"
+ "</div>";
}
+ os<< "</div>";
}
std::size_t process_id()
@@ -74,24 +106,43 @@
}
response resp;
- resp<< content_type("text/html")
- << "Request ID = " << req.id() << "<br />"
- << "Process ID = " << process_id() << "<br />"
- << "<form method=POST enctype='multipart/form-data'>"
- "<input type=text name=name value='" << req[post]["name"] << "' />"
- "<br />"
- "<input type=text name=hello value='" << req[post]["hello"] << "' />"
- "<br />"
- "<input type=file name=user_file />"
- "<input type=hidden name=cmd value=multipart_test />"
- "<br />"
- "<input type=submit value=submit />"
- "</form><p />";
-
- show_map_contents(resp, req[env], "Environment Variables");
- show_map_contents(resp, req[get], "GET Variables");
- show_map_contents(resp, req[post], "POST Variables");
- show_map_contents(resp, req[cookies], "Cookie Variables");
+ resp<< content_type("text/html") <<
+ "<html>"
+ "<head>"
+ "<title>CGI Echo Example</title>"
+ "<style type=\"text/css\">"
+ << gCSS_text <<
+ "</style>"
+ "<head>"
+ "<body>"
+ "Request ID = " << req.id() << "<br />"
+ "Process ID = " << process_id() << "<br />"
+ "<form method=POST enctype='multipart/form-data'>"
+ "<input type=text name=name value='"
+ << req[post]["name"] << "' />"
+ "<br />"
+ "<input type=text name=hello value='"
+ << req[post]["hello"] << "' />"
+ "<br />"
+ "<input type=file name=user_file />"
+ "<input type=hidden name=cmd value=multipart_test />"
+ "<br />"
+ "<input type=submit value=submit />"
+ "</form><p />";
+
+ format_map(resp, req[env], "Environment Variables");
+ format_map(resp, req[get], "GET Variables");
+ format_map(resp, req[post], "POST Variables");
+ format_map(resp, req[cookies], "Cookie Variables");
+
+ resp<< "<pre>";
+ BOOST_FOREACH(char& ch, req.post_buffer())
+ {
+ resp<< ch;
+ }
+ resp<< "</pre>"
+ "</body>"
+ "</html>";
return_(resp, req, 0); // All ok.
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -27,5 +27,7 @@
[include fcgi/doc.qbk]
-[endsect]
+[include xcgi/doc.qbk]
+
+[endsect][/ examples]
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -3,6 +3,10 @@
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.
+[note
+ You need to download and install [@http://code.google.com/p/google-ctemplate Google's cTemplate library] and you may have to modify Jamfile.v2 to point to your compiled ctemplate library (see the `lib ctemplate ...` lines).
+]
+
[import main.cpp]
[fcgi_amort]
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -14,14 +14,11 @@
// Note that GET and cookie variables come from the environment
// variables QUERY_STRING and HTTP_COOKIE respectively.
//
-
-#include <fstream>
///////////////////////////////////////////////////////////
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/program_options/environment_iterator.hpp>
///////////////////////////////////////////////////////////
#include "boost/cgi/fcgi.hpp"
-#include "boost/cgi/common/header.hpp"
using namespace std;
using namespace boost::fcgi;
@@ -29,20 +26,50 @@
// This is a file to put internal logging info into
#define LOG_FILE "/var/www/log/fcgi_echo.txt"
+// The styling information for the page, just to make things look nicer.
+static const char* gCSS_text =
+"body { padding: 0; margin: 3%; border-color: #efe; }"
+".var_map_title"
+ "{ font-weight: bold; font-size: large; }"
+".var_map"
+ "{ border: 1px dotted; padding: 2px 3px 2px 3px; margin-bottom: 3%; }"
+".var_pair"
+ "{ border-top: 1px dotted; overflow: auto; padding: 0; margin: 0; }"
+".var_name"
+ "{ position: relative; float: left; width: 30%; font-weight: bold; }"
+".var_value"
+ "{ position: relative; float: left; width: 65%; left: 1%;"
+ " border-left: 1px solid; padding: 0 5px 0 5px;"
+ " overflow: auto; white-space: pre; }"
+;
+
//
-// Write the title and map contents to the ostream in an HTML-encoded
-// format (to make them easier on the eye).
+// 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(OStream& os, Map& m, const std::string& title)
+template<typename OStreamT, typename MapT>
+void format_map(OStreamT& os, MapT& m, 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 />";
- }
+ os<< "<div class=\"var_map\">"
+ "<div class=\"var_map_title\">"
+ << title
+ << "</div>";
+
+ if (m.empty())
+ os<< "<div class=\"var_pair\">EMPTY</div>";
+ else
+ for (typename MapT::const_iterator i = m.begin(); i != m.end(); ++i)
+ {
+ os<< "<div class=\"var_pair\">"
+ "<div class=\"var_name\">"
+ << i->first
+ << "</div>"
+ "<div class=\"var_value\">"
+ << i->second
+ << "</div>"
+ "</div>";
+ }
+ os<< "</div>";
}
std::size_t process_id()
@@ -54,16 +81,13 @@
#endif
}
+
/// This function accepts and handles a single request.
-template<typename Request, typename LogStream>
-int handle_request(Request& req, LogStream& of)
+template<typename Request>
+int handle_request(Request& req)
{
boost::system::error_code ec;
- of<< "Called accept" << endl;
- // Result should be "Success".
- of<< "Accept had result: " << ec.message() << endl;
-
//
// Load in the request data so we can access it easily.
//
@@ -78,39 +102,59 @@
// 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 />"
- << "Request id = " << req.id() << "<p />"
- << "Process id = " << process_id() << "<p />"
- << "<form method=POST enctype='multipart/form-data'>"
- "<input type=text name=name value='" << req[post]["name"] << "' />"
- "<br />"
- "<input type=text name=hello value='" << req[post]["hello"] << "' />"
- "<br />"
- "<input type=file name=user_file />"
- "<input type=hidden name=cmd value=multipart_test />"
- "<br />"
- "<input type=submit value=submit />"
- "</form><p />";
+ resp<< content_type("text/html");
+
+ // You can also stream text to a response.
+ // All of this just prints out the form
+ resp<< "<html>"
+ "<head>"
+ "<title>FastCGI Echo Example</title>"
+ "<style type=\"text/css\">"
+ << gCSS_text <<
+ "</style>"
+ "<head>"
+ "<body>"
+ "Request ID = " << req.id() << "<br />"
+ "Process ID = " << process_id() << "<br />"
+ "<form method=POST enctype='multipart/form-data'>"
+ "<input type=text name=name value='"
+ << req[post]["name"] << "' />"
+ "<br />"
+ "<input type=text name=hello value='"
+ << req[post]["hello"] << "' />"
+ "<br />"
+ "<input type=file name=user_file />"
+ "<input type=hidden name=cmd value=multipart_test />"
+ "<br />"
+ "<input type=submit value=submit />"
+ "</form><p />";
//
// Use the function defined above to show some of the request data.
+ // (this function isn't part of the library)
//
format_map(resp, req[env], "Environment Variables");
format_map(resp, req[get], "GET Variables");
format_map(resp, req[post], "POST Variables");
format_map(resp, req[cookies], "Cookie Variables");
+ // Print the complete buffer containing the POST data and the FastCGI params.
+ resp<< "<pre>";
+ BOOST_FOREACH(char& ch, req.post_buffer())
+ {
+ resp<< ch;
+ }
+ // << req.get_buffer()
+ resp<< "</pre>";
+
//
// Response headers can be added at any time before send/flushing it:
//
- resp<< "<content-length == "
- << content_length(resp)
- << content_length(resp) << ">";
+ resp<< "Response content-length == "
+ << resp.content_length() // the content-length (returns std::size_t)
+ << content_length(resp) // a content-length header
+ << ">";
- //
- //
// This funky macro finishes up:
return_(resp, req, 0);
//
@@ -129,16 +173,6 @@
{
try {
- ofstream of(LOG_FILE);
- if (!of)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- return 1;
- }
-
- of<< boost::posix_time::second_clock::local_time() << endl;
- of<< "Going to start acceptor." << endl;
-
// Make a `service` (more about this in other examples).
service s;
// Make an `acceptor` for accepting requests through.
@@ -153,27 +187,34 @@
{
request req(s);
//
- // Now we enter another loop that reuses the request's connection (and
- // memory - makes things more efficient). You should always do this for
- // now; this requirement will be removed in future.
+ // Now we enter another loop that reuses the request's memory - makes
+ // things more efficient). You should always do this for
+ // now; this requirement might be removed in future.
//
for (;;)
{
a.accept(req);
- ret = handle_request(req, of);
- of<< "handle_request() returned: " << ret << endl;
+ ret = handle_request(req);
if (ret)
break;
+ //
+ // Clear the request's data, so information doesn't pass between
+ // different users (this step isn't really necessary, because
+ // the library will do this automatically.
+ //
+ req.clear();
}
}
return ret;
}catch(boost::system::system_error& se){
+ // This is the type of error thrown by the library.
cerr<< "[fcgi] System error: " << se.what() << endl;
return 1313;
-}catch(exception& e){
- cerr<< "[fcgi] Exception: " << e.what() << endl;
+}catch(exception* e){
+ // Catch any other exceptions
+ cerr<< "[fcgi] Exception: " << e->what() << endl;
return 666;
}catch(...){
cerr<< "[fcgi] Uncaught exception!" << endl;
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -18,15 +18,16 @@
using namespace std;
using namespace boost::fcgi;
-=======
-/// Handle a FastCGI request
-template<typename Acceptor>
-int handle_request(Acceptor& a)
+template<typename Request, typename Response>
+int handle_request(Request& req, Response& resp)
{
- int ret = 0;
- for (;;) // Handle requests until something goes wrong
- // (an exception will be thrown).
->>>>>>> .r46066
+ // This is a minimal response. The content_type(...) may go before or after
+ // the response text.
+ resp<< content_type("text/plain")
+ << "Hello there, universe.";
+
+ return_(resp, req, 0);
+}
int main()
{
@@ -34,6 +35,8 @@
{
service s; // This becomes useful with async operations.
acceptor a(s);
+
+ int ret = 0; // the return value
for (;;)
{
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -1,11 +1,17 @@
-[section Hello world]
+[section Handling CGI and FastCGI]
[import main.cpp]
-[acgi_hello_world]
+[note
+ The key bit of this example is making an fcgi::service and fcgi::acceptor and
+ then using the acceptor to check if the program is running in FastCGI or
+ CGI mode - by calling `fcgi::acceptor::is_cgi()` - then you handle it accordingly.
+]
-See the [@../../example/acgi/hello_world/main.cpp full source listing].
+[xcgi_basic]
+
+See the [@../../example/xcgi/basic/main.cpp full source listing].
[endsect][/ hello_world]
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/doc.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -0,0 +1,9 @@
+
+[section Protocol-independent Examples]
+
+[include basic/doc.qbk]
+
+[include server1/doc.qbk]
+
+[endsect]
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -1,8 +1,8 @@
#ifndef BOOST_CGI_EXAMPLES_XCGI_SERVER2_SERVER_HPP_INCLUDED_
#define BOOST_CGI_EXAMPLES_XCGI_SERVER2_SERVER_HPP_INCLUDED_
-#include <boost/cgi/fcgi.hpp>
-#include <boost/cgi/acgi.hpp>
+//[xcgi_server1_server
+#include <boost/cgi.hpp>
class Server
{
@@ -35,7 +35,7 @@
template<typename Handler>
int handle_fcgi_requests(Handler handler)
{
- boost::fcgi::request req(acceptor_.protocol_service());
+ boost::fcgi::request req(service_);
int ret = 0;
for (;;) // Handle requests until something goes wrong
@@ -51,6 +51,7 @@
boost::fcgi::service service_;
boost::fcgi::acceptor acceptor_;
};
+//]
#endif // BOOST_CGI_EXAMPLES_XCGI_SERVER2_SERVER_HPP_INCLUDED_
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -1,11 +1,25 @@
-[section Hello world]
+[section A Simple Dispatcher]
[import main.cpp]
+[import Server.hpp]
-[acgi_hello_world]
+First, the Server class, which can dispatch both CGI and FastCGI requests.
+The handler passed to `Server::run()` must be able to deal with both
+`boost::acgi::request` and `boost::fcgi::request` types. An example handler is
+in `main.cpp` (shown below), which deals with all types.
-See the [@../../example/acgi/hello_world/main.cpp full source listing].
+[xcgi_server1_server]
-[endsect][/ hello_world]
+The `request_handler` is the important part of the example below, the part you
+should supply.
+
+[xcgi_server1]
+
+See the full source listing: [: [@../../example/xcgi/server1/Server.hpp Server.hpp]
+
+ [@../../example/xcgi/server1/main.cpp main.cpp]
+]
+
+[endsect][/ a_simple_dispatcher]
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -7,23 +7,23 @@
//
////////////////////////////////////////////////////////////////
//
-//[xcgi_server2
+//[xcgi_server1
//
// A protocol-independent program, outputs only
//
// "Hello there, universe."
//
-// This one is similar to the xcgi/basic example and equally simple, but here
-// the protocol-dependent bits done by `Server` class (see "Server.hpp").
+// This one is similar to the xcgi/basic example and even more straigh-forward
+// simple. The difference here is that the protocol-dependent bits are done by
+// `Server` class (see "Server.hpp"). All the Server object takes is a handler
+// that is a function object with a compatible signature.
//
-// example/xcgi/basic$ `bjam install`
+// example/xcgi/server1$ `bjam install`
//
// will install the example to your cgi-bin and fcgi-bin. Look
// [link ../../doc.qbk here] for more information, including how to set these.
//
-#include <boost/cgi/fcgi.hpp>
-#include <boost/cgi.hpp>
#include "Server.hpp"
using namespace std;
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/src/library_sources.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/src/library_sources.cpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -0,0 +1,36 @@
+
+/**
+ * Include this file into your project to compile the library "in-place".
+ *
+ * If you're using Boost.Jam, the library can be built by specifying
+ * "--build-cgi" on the command line.
+ *
+ * eg.
+ * libs/cgi/build$ bjam --build-cgi (builds the library)
+ *
+ * libs/cgi/example$ bjam --build-cgi install
+ *
+ * (builds and installs all the examples using the compiled binary
+ * - which will be installed if necessary - see the docs for more)
+ *
+**/
+
+#ifndef BOOST_CGI_LIBRARY_SOURCES_INCLUDE_ONCE
+# define BOOST_CGI_LIBRARY_SOURCES_INCLUDE_ONCE
+#else
+# error "CGI library sources included twice (don't do that)."
+#endif
+
+#ifndef BOOST_CGI_BUILD_LIB
+# warning "BOOST_CGI_BUILD_LIB not defined (are you sure you want to "
+# warning "build the library?)"
+# warning "Building anyway"
+# define BOOST_CGI_BUILD_LIB
+#endif // BOOST_CGI_BUILD_LIB
+
+//////////// the sources
+//#include <boost/cgi/impl/form_parser.ipp>
+//#include <boost/cgi/impl/response.ipp>
+#include <boost/cgi/impl/fcgi_request_service.ipp>
+#include <boost/cgi/detail/url_decode.ipp>
+
Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/Jamfile.v2 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -5,7 +5,6 @@
project boost/cgi/tests/run
: requirements
- <include>/usr/local/src/boost/sandbox/SOC/2006/process/tags/process-0.1
<library>/boost/test//boost_unit_test_framework/
<library>/boost/system/
<library>/boost/thread/
@@ -29,6 +28,7 @@
[ run acgi_simple_request.cpp ]
[ run name_test.cpp ]
[ run map_test.cpp ]
+ [ run parse_options.cpp ]
;
test-suite wget_test
Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/parse_options.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/parse_options.cpp 2008-06-18 16:01:37 EDT (Wed, 18 Jun 2008)
@@ -0,0 +1,32 @@
+
+#include "boost/cgi/common/parse_options.hpp"
+#define BOOST_TEST_MODULE parse_options_test
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( test_parse_options )
+{
+ using namespace cgi::common;
+
+ {
+ parse_options opt = parse_env;
+ BOOST_CHECK(opt < parse_get);
+ BOOST_CHECK(opt < parse_post);
+ BOOST_CHECK(opt < parse_cookie);
+ BOOST_CHECK(opt < parse_all);
+ }
+
+ {
+ parse_options opt = parse_form;
+ BOOST_CHECK(opt & parse_get);
+ BOOST_CHECK(opt & parse_post);
+ }
+
+ {
+ parse_options opt = parse_all;
+ BOOST_CHECK(opt & parse_env);
+ BOOST_CHECK(opt & parse_get);
+ BOOST_CHECK(opt & parse_post);
+ BOOST_CHECK(opt & parse_cookie);
+ }
+}
+
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