|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r58110 - in sandbox/SOC/2007/cgi/branches/pickmeup: boost/cgi boost/cgi/common boost/cgi/detail boost/cgi/fcgi boost/cgi/http boost/cgi/impl libs/cgi/build/msvc/9.0/Boost.CGI libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world libs/cgi/example/fcgi/echo libs/cgi/example/fcgi/hello_world
From: lists.drrngrvy_at_[hidden]
Date: 2009-12-02 22:43:01
Author: drrngrvy
Date: 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
New Revision: 58110
URL: http://svn.boost.org/trac/boost/changeset/58110
Log:
[Tested: MSVC9.0]
* Refactoring basic_client so FastCGI reuses the same functionality for the most part.
* Fixed an issue with FastCGI where the HTTP server would close the connection if the response was sent before the entire request had been read from the server. Modified fcgi_request_service::close() to read all of the data if it hasn't already been read.
* Other code cleanups.
Added:
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/response.hpp (contents, props changed)
Binary files modified:
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.suo
Text files modified:
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp | 144 ++++++++++++--
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp | 11
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/error.hpp | 2
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp | 9
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/protocol_traits.hpp | 40 +--
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp | 406 ++++++++++++---------------------------
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp | 5
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp | 4
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/specification.hpp | 1
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/http/status_code.hpp | 6
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp | 113 +++-------
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp | 47 +++-
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj | 1
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp | 4
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/hello_world/main.cpp | 1
15 files changed, 367 insertions(+), 427 deletions(-)
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -15,11 +15,23 @@
#include "boost/cgi/http/status_code.hpp"
#include "boost/cgi/common/role_type.hpp"
#include "boost/cgi/common/request_status.hpp"
+#include "boost/cgi/detail/protocol_traits.hpp"
#include "boost/cgi/connections/tcp_socket.hpp"
BOOST_CGI_NAMESPACE_BEGIN
namespace common {
+
+ enum client_status
+ {
+ none_, // **FIXME** !
+ constructed,
+ params_read,
+ stdin_read,
+ end_request_sent,
+ closed_, // **FIXME** !
+ //aborted
+ };
/// A client
/**
@@ -44,9 +56,18 @@
{
public:
//typedef BOOST_CGI_NAMESPACE::map map_type;
+ typedef ::BOOST_CGI_NAMESPACE::common::io_service io_service_type;
+ typedef ::BOOST_CGI_NAMESPACE::common::map map_type;
typedef Connection connection_type;
typedef Protocol protocol_type;
typedef typename connection_type::pointer connection_ptr;
+ typedef boost::array<unsigned char, 8> header_buffer_type;
+ typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+ typedef typename
+ detail::protocol_traits<
+ Protocol
+ >::role_type role_type;
+
basic_client()
{
@@ -56,33 +77,52 @@
//: io_service_(ios)
{
}
-
- bool is_open()
- {
- return connection_->is_open();
- }
-
- void close()
- {
- connection_->close();
- }
-
- boost::uint16_t const& request_id() const
- {
- return 1;
+
+ /// Construct the client by claiming a request id.
+ /**
+ * Before loading a request, it will usually not have a request id. This
+ * function reads headers (and corresponding bodies if necessary) until
+ * a BEGIN_REQUEST record is found. The calling request then claims and
+ * serves that request.
+ */
+ template<typename RequestImpl>
+ boost::system::error_code
+ construct(RequestImpl& req, boost::system::error_code& ec)
+ {
+ status_ = constructed;
+ return ec;
+ }
+
+ boost::system::error_code
+ close(boost::uint64_t app_status, boost::system::error_code& ec)
+ {
+ if (!is_open())
+ ec = error::already_closed;
+ else
+ {
+ status_ = closed_;
+ connection_->close();
+ }
+ }
+
+ void close(boost::uint64_t app_status = 0)
+ {
+ boost::system::error_code ec;
+ close(app_status, ec);
+ detail::throw_error(ec);
}
/// Associate a connection with this client
/**
* Note: the connection must have been created using the new operator
- *
+ */
bool set_connection(connection_type* conn)
{
// make sure there isn't already a connection associated with the client
- if (!connection_) return false;
+ //if (!connection_) return false;
connection_.reset(conn);
return true;
- }*/
+ }
//io_service& io_service() { return io_service_; }
@@ -99,10 +139,6 @@
return true;
}
- /// Get a shared_ptr of the connection associated with the client.
- connection_ptr& connection() { return connection_; }
- std::size_t& bytes_left() { return bytes_left_; }
-
/// Write some data to the client.
template<typename ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence& buf
@@ -111,7 +147,20 @@
return connection_->write_some(buf, ec);
}
- /// Read some data from the client.
+ /// 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)
@@ -145,6 +194,41 @@
{
connection_->async_read_some(buf, handler);
}
+
+
+ ////// Querying the client.
+
+ /// Get a shared_ptr of the connection associated with the client.
+ connection_ptr& connection() { return connection_; }
+ std::size_t& bytes_left() { return bytes_left_; }
+
+ bool is_open()
+ {
+ return connection_->is_open();
+ }
+
+ /// Get the status of the client.
+ const client_status& status() const
+ {
+ return status_;
+ }
+
+ /// Set the status of the client.
+ void status(client_status status)
+ {
+ status_ = status;
+ }
+
+ bool keep_connection() const
+ {
+ return keep_connection_;
+ }
+
+ boost::uint16_t const& request_id() const
+ {
+ return request_id_;
+ }
+
private:
//io_service& io_service_;
connection_ptr connection_;
@@ -152,6 +236,22 @@
public: // **FIXME**
// we should never read more than content-length bytes.
std::size_t bytes_left_;
+
+ boost::uint16_t request_id_;
+ client_status status_;
+
+ boost::uint64_t total_sent_bytes_;
+ boost::uint64_t total_sent_packets_;
+
+ /// Buffer used to check the header of each packet.
+ //header_buffer_type out_header_;
+ fcgi::spec::header header_;
+
+ /// Output buffer.
+ std::vector<boost::asio::const_buffer> outbuf_;
+
+ bool keep_connection_;
+ role_type role_;
};
} // namespace common
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -155,18 +155,21 @@
return impl->count(key);
}
- mapped_type& get(key_type const& key, mapped_type const& default_)
+ mapped_type const&
+ get(key_type const& key, mapped_type const& default_) const
{
BOOST_ASSERT(impl);
const_iterator iter = impl->find(key);
- return iter == impl->end() > default_ : *iter;
+ return iter == impl->end() ? default_ : iter->second;
}
template<typename T>
T as(key_type const& key) {
BOOST_ASSERT(impl);
- mapped_type& val((*impl)[key]);
- return val.empty() ? T() : boost::lexical_cast<T>(val);
+ const_iterator iter = impl->find(key);
+ return iter == impl->end()
+ ? T()
+ : boost::lexical_cast<T>(val);
}
mapped_type& operator[](key_type const& varname) {
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/error.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/error.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/error.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -67,6 +67,8 @@
// Expected a boundary marker for a multipart form, but did not find it.
no_boundary_marker,
+ already_closed,
+
// The content length of the file upload is larger than maximum allowed
// by the BOOST_CGI_POST_MAX macro.
max_post_exceeded
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -141,9 +141,9 @@
/// Get the contents of the response as a string.
/**
* This copies the contents of the response into a string.
- * Headers aren't included in the dump.
+ * Headers aren't included in the dump unless `include_header` is true.
*/
- string_type str() const;
+ string_type str(bool include_header = false) const;
/// Format and add a header given name and value, appending CRLF.
basic_response<char_type>&
@@ -155,7 +155,10 @@
void reset_headers();
- string_type& charset() { return charset_; }
+ /// Get the charset.
+ string_type& charset() const { return charset_; }
+ /// Set the charset.
+ void charset(string_type const& cs) { charset_ = cs; }
bool headers_terminated() const;
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/protocol_traits.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/protocol_traits.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/protocol_traits.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -16,10 +16,13 @@
#ifndef CGI_REQUEST_TRAITS_HPP_INCLUDED__
#define CGI_REQUEST_TRAITS_HPP_INCLUDED__
+#include <boost/none.hpp>
#include <boost/shared_ptr.hpp>
///////////////////////////////////////////////////////////
#include "boost/cgi/fwd/basic_protocol_service_fwd.hpp"
#include "boost/cgi/common/tags.hpp"
+#include "boost/cgi/common/role_type.hpp"
+#include "boost/cgi/fcgi/specification.hpp"
#include "boost/cgi/fwd/basic_request_fwd.hpp"
#include "boost/cgi/fwd/basic_connection_fwd.hpp"
@@ -42,8 +45,6 @@
{
class fcgi_request_impl;
class fcgi_service_impl;
- class fcgi_gateway_impl;
- class fcgi_gateway_service;
class fcgi_request_service;
class fcgi_acceptor_service;
}
@@ -51,8 +52,6 @@
{
class scgi_request_impl;
class scgi_service_impl;
- class scgi_gateway_impl;
- class scgi_gateway_service;
class scgi_request_service;
class scgi_acceptor_service;
}
@@ -64,23 +63,11 @@
class async_cgi_request_impl;
class fcgi_request_impl;
- //template<typename>
class cgi_service_impl;
class acgi_service_impl;
class async_cgi_service_impl;
class fcgi_service_impl;
- class cgi_gateway_impl;
- class acgi_gateway_impl;
- class async_cgi_gateway_impl;
- class fcgi_gateway_impl;
-
- class cgi_gateway_service;
- class acgi_gateway_service;
- class async_cgi_gateway_service;
- class fcgi_gateway_service;
- template<typename> class gateway_service;
-
class acgi_acceptor_service;
class fcgi_acceptor_service;
@@ -112,8 +99,8 @@
> request_type;
typedef cgi_service_impl service_impl_type;
typedef common::basic_connection<tags::stdio> connection_type;
-// typedef cgi_gateway_impl gateway_impl_type;
-// typedef cgi_gateway_service gateway_service_impl_type;
+ typedef boost::none_t header_type;
+ typedef common::role_type role_type;
};
template<>
@@ -133,13 +120,12 @@
typedef common::basic_connection<
tags::async_stdio
> connection_type;
- typedef async_cgi_gateway_impl gateway_impl_type;
- typedef async_cgi_gateway_service gateway_service_type;
+ typedef boost::none_t header_type;
+ typedef common::role_type role_type;
};
template<>
struct protocol_traits<tags::acgi>
- // : protocol_traits<tags::async_cgi>
{
typedef protocol_traits<tags::acgi> type;
typedef acgi::request_impl impl_type;
@@ -154,8 +140,8 @@
typedef common::basic_connection<
tags::async_stdio
> connection_type;
- typedef acgi_gateway_impl gateway_impl_type;
- typedef acgi_gateway_service gateway_service_type;
+ typedef boost::none_t header_type;
+ typedef common::role_type role_type;
};
template<>
@@ -172,15 +158,13 @@
, protocol_service_type
> request_type;
typedef boost::shared_ptr<request_type> request_ptr;
- //typedef fcgi_request_service
- // ::implementation_type request_impl_type;
typedef fcgi::fcgi_service_impl service_impl_type;
typedef fcgi::fcgi_acceptor_service acceptor_service_impl;
typedef common::basic_connection<
tags::shareable_tcp_socket
> connection_type;
- //typedef fcgi_gateway_impl gateway_impl_type;
- //typedef fcgi_gateway_service gateway_service_type;
+ typedef fcgi::spec::header header_type;
+ typedef fcgi::spec_detail::role_types role_type;
};
template<>
@@ -196,8 +180,6 @@
typedef scgi::scgi_service_impl service_impl_type;
typedef scgi::scgi_acceptor_service acceptor_service_impl;
typedef common::basic_connection<tags::tcp_socket> connection_type;
- //typedef scgi_gateway_impl gateway_impl_type;
- //typedef scgi_gateway_service gateway_service_type;
};
// **FIXME** (remove)
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -35,313 +35,167 @@
BOOST_CGI_NAMESPACE_BEGIN
namespace common {
- enum client_status
- {
- none_, // **FIXME** !
- constructed,
- params_read,
- stdin_read,
- end_request_sent,
- closed_, // **FIXME** !
- //aborted
- };
-
/// A client that uses a TCP socket that owned by it.
- template<typename Protocol>
- class basic_client<connections::shareable_tcp, Protocol>
+ /// Construct
+ template<>
+ basic_client<
+ connections::shareable_tcp
+ , ::BOOST_CGI_NAMESPACE::common::tags::fcgi
+ >::basic_client()
+ : request_id_(-1)
+ , status_(none_)
+ , keep_connection_(false)
+ , total_sent_bytes_(0)
+ , total_sent_packets_(0)
+ , header_()
+ , outbuf_()
{
- public:
- typedef ::BOOST_CGI_NAMESPACE::common::io_service io_service_type;
- typedef ::BOOST_CGI_NAMESPACE::common::map map_type;
- typedef Protocol protocol_type;
- typedef connections::shareable_tcp connection_type;
- typedef typename connection_type::pointer connection_ptr;
- typedef boost::array<
- unsigned char
- , fcgi::spec::header_length::value
- > header_buffer_type;
- typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
- typedef fcgi::spec_detail::role_types role_type;
-
- /// Construct
- basic_client()
- : request_id_(-1)
- , status_(none_)
- , keep_connection_(false)
- , total_sent_bytes_(0)
- , total_sent_packets_(0)
- , header_()
- , outbuf_()
- {
- }
+ }
- /// Construct
- basic_client(io_service_type& ios)
- : request_id_(-1)
- , status_(none_)
- , keep_connection_(false)
- , total_sent_bytes_(0)
- , total_sent_packets_(0)
- , header_()
- , outbuf_()
- {
- }
-
- /// Destroy
- /** Closing the connection as early as possible is good for efficiency */
- ~basic_client()
- {
- close();
- }
-
- /// Construct the client by claiming a request id.
- /**
- * Before loading a request, it will usually not have a request id. This
- * function reads headers (and corresponding bodies if necessary) until
- * a BEGIN_REQUEST record is found. The calling request then claims and
- * serves that request.
- */
- template<typename RequestImpl>
- boost::system::error_code
- construct(RequestImpl& req, boost::system::error_code& ec)
- {
- status_ = constructed;
- return ec;
- }
-
- bool is_open() const
- {
- return connection_->is_open();
- }
-
- void close(boost::uint64_t app_status = 0)
- {
- boost::system::error_code ec;
- close(app_status, ec);
- detail::throw_error(ec);
- }
+ /// Construct
+ template<>
+ basic_client<
+ connections::shareable_tcp
+ , ::BOOST_CGI_NAMESPACE::common::tags::fcgi
+ >::basic_client(io_service_type& ios)
+ : request_id_(-1)
+ , status_(none_)
+ , keep_connection_(false)
+ , total_sent_bytes_(0)
+ , total_sent_packets_(0)
+ , header_()
+ , outbuf_()
+ {
+ }
- boost::system::error_code
- close(boost::uint64_t app_status, boost::system::error_code& ec)
+ /// Override basic_client::close().
+ /**
+ * Closing a FastCGI means sending an END_REQUEST header
+ * to the HTTP server and potentially closing the connection.
+ *
+ * Note that in general the HTTP server is responsible for the
+ * lifetime of the connection, but can hand that control over
+ * to the library (eg. if the server is set up to recycle
+ * connections after N requests).
+ */
+ template<>
+ boost::system::error_code
+ basic_client<
+ connections::shareable_tcp
+ , ::BOOST_CGI_NAMESPACE::common::tags::fcgi
+ >::close(boost::uint64_t app_status, boost::system::error_code& ec)
+ {
+ // Note that the request may already be closed if the client aborts
+ // the connection.
+ if (!is_open())
+ ec = error::already_closed;
+ else
{
- // We can safely ignore this next bit when the connection
- // is already closed. This might happen when the client aborts
- // the connection.
- if (!ec && status_ != closed_ && connection_->is_open())
- {
- outbuf_.clear();
- header_.reset(fcgi::spec_detail::END_REQUEST, request_id_, 8);
+ status_ = closed_;
+ outbuf_.clear();
+ header_.reset(fcgi::spec_detail::END_REQUEST, request_id_, 8);
- // Write an EndRequest packet to the server.
- fcgi::spec::end_request_body body(
- app_status, fcgi::spec_detail::REQUEST_COMPLETE);
+ // Write an EndRequest packet to the server.
+ fcgi::spec::end_request_body body(
+ app_status, fcgi::spec_detail::REQUEST_COMPLETE);
- outbuf_.push_back(header_.data());
- outbuf_.push_back(body.data());
+ outbuf_.push_back(header_.data());
+ outbuf_.push_back(body.data());
- write(*connection_, outbuf_, boost::asio::transfer_all(), ec);
+ write(*connection_, outbuf_, boost::asio::transfer_all(), ec);
- if (!ec && !keep_connection_)
- {
- connection_->close();
- }
- }
-
- if (ec && !keep_connection_)
+ if (!ec && !keep_connection_)
{
- // If there was an error writing to the client, we can ignore it
- // unless the `keep_connection_` flag is set.
- // The client has likely aborted the request if we reach here.
- ec = boost::system::error_code();
+ connection_->close();
}
- return ec;
}
+ return ec;
+ }
- /// Associate a connection with this client
- /**
- * Note: the connection must have been created using the new operator
- */
- bool set_connection(connection_type* conn)
- {
- // make sure there isn't already a connection associated with the client
- //if (!connection_) return false;
- connection_.reset(conn);
- return true;
- }
+ /// Write some data to the client.
+ template<>
+ template<typename ConstBufferSequence>
+ std::size_t
+ basic_client<
+ connections::shareable_tcp
+ , ::BOOST_CGI_NAMESPACE::common::tags::fcgi
+ >::write_some(
+ const ConstBufferSequence& buf
+ , boost::system::error_code& ec
+ )
+ {
+ typename ConstBufferSequence::const_iterator iter = buf.begin();
+ typename ConstBufferSequence::const_iterator end = buf.end();
- /// Associate a connection with this client
- bool set_connection(const connection_type::pointer& conn)
- {
- // make sure there isn't already a connection associated with the client
- //if (!connection_) return false;
- connection_ = conn;
- return true;
- }
+ outbuf_.clear();
+ outbuf_.push_back(boost::asio::buffer(header_.data()));
- /// Get a shared_ptr of the connection associated with the client.
- connection_type::pointer&
- 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)
+ int total_buffer_size(0);
+ for(; iter != end; ++iter)
{
- typename ConstBufferSequence::const_iterator iter = buf.begin();
- typename ConstBufferSequence::const_iterator end = buf.end();
-
- outbuf_.clear();
- outbuf_.push_back(boost::asio::buffer(header_.data()));
-
- int total_buffer_size(0);
- for(; iter != end; ++iter)
+ boost::asio::const_buffer buffer(*iter);
+ std::size_t new_buf_size( boost::asio::buffer_size(*iter) );
+ if (total_buffer_size + new_buf_size
+ > static_cast<std::size_t>(fcgi::spec::max_packet_size::value))
{
- boost::asio::const_buffer buffer(*iter);
- std::size_t new_buf_size( boost::asio::buffer_size(*iter) );
- if (total_buffer_size + new_buf_size
- > static_cast<std::size_t>(fcgi::spec::max_packet_size::value))
+ // If the send buffer is empty, extract a chunk of the
+ // new buffer to send. If there is already some data
+ // ready to send, don't add any more data to the pack.
+ if (total_buffer_size == 0)
{
- // If the send buffer is empty, extract a chunk of the
- // new buffer to send. If there is already some data
- // ready to send, don't add any more data to the pack.
- if (total_buffer_size == 0)
- {
- total_buffer_size
- = std::min<std::size_t>(new_buf_size,65500);
- /*
- std::cerr<< "Oversized buffer: " << total_buffer_size
- << " / " << new_buf_size << " bytes sent\n";
- */
- outbuf_.push_back(
- boost::asio::buffer(*iter, total_buffer_size));
- break;
- }
- else
- break;
+ total_buffer_size
+ = std::min<std::size_t>(new_buf_size,65500);
+ /*
+ std::cerr<< "Oversized buffer: " << total_buffer_size
+ << " / " << new_buf_size << " bytes sent\n";
+ */
+ outbuf_.push_back(
+ boost::asio::buffer(*iter, total_buffer_size));
+ break;
}
else
- {
- total_buffer_size += new_buf_size;
- outbuf_.push_back(*iter);
- }
+ break;
+ }
+ else
+ {
+ total_buffer_size += new_buf_size;
+ outbuf_.push_back(*iter);
}
- header_.reset(fcgi::spec_detail::STDOUT, request_id_, total_buffer_size);
-
- std::size_t bytes_transferred
- = boost::asio::write(*connection_, outbuf_
- , boost::asio::transfer_all(), ec);
-
-
- std::cerr<< "Transferred " << bytes_transferred
- << " / " << total_buffer_size << " bytes (running total: "
- << total_sent_bytes_ << " bytes; "
- << total_sent_packets_ << " packets).\n";
- if (ec)
- std::cerr<< "Error " << ec << ": " << ec.message() << '\n';
-
- total_sent_bytes_ += bytes_transferred;
- total_sent_packets_ += 1;
- // Now remove the protocol overhead from the caller, who
- // doesn't care about them.
- bytes_transferred -= fcgi::spec::header_length::value;
- // Check everything was written ok.
- if (!ec && bytes_transferred != total_buffer_size)
- ec = ::BOOST_CGI_NAMESPACE::fcgi::error::couldnt_write_complete_packet;
-
- 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)
- {
- return connection_->read_some(buf, ec);
- }
-
- /// Asynchronously write some data to the client.
- template<typename ConstBufferSequence, typename Handler>
- void async_write_some(const ConstBufferSequence& buf, Handler handler)
- {
- connection_->async_write_some(buf, handler);
- }
-
- /// Asynchronously read some data from the client.
- template<typename MutableBufferSequence, typename Handler>
- void async_read_some(const MutableBufferSequence& buf, Handler handler)
- {
- connection_->async_read_some(buf, handler);
- }
-
-
- /// Get the status of the client.
- const client_status& status() const
- {
- return status_;
- }
-
- /// Set the status of the client.
- void status(client_status status)
- {
- status_ = status;
- }
-
- bool keep_connection() const
- {
- return keep_connection_;
- }
-
- std::size_t& bytes_left()
- {
- return bytes_left_;
- }
-
- boost::uint16_t const& request_id() const
- {
- return request_id_;
}
-
- public:
- friend class fcgi_request_service;
- boost::uint16_t request_id_;
- client_status status_;
- std::size_t bytes_left_;
- connection_ptr connection_;
+ header_.reset(fcgi::spec_detail::STDOUT, request_id_, total_buffer_size);
- boost::uint64_t total_sent_bytes_;
- boost::uint64_t total_sent_packets_;
-
- /// Buffer used to check the header of each packet.
- //header_buffer_type out_header_;
- fcgi::spec::header header_;
+ std::size_t bytes_transferred
+ = boost::asio::write(*connection_, outbuf_
+ , boost::asio::transfer_all(), ec);
- /// Output buffer.
- std::vector<boost::asio::const_buffer> outbuf_;
-
- bool keep_connection_;
- role_type role_;
+ total_sent_bytes_ += bytes_transferred;
+ total_sent_packets_ += 1;
+
+ if (ec)
+ std::cerr<< "Error " << ec << ": " << ec.message() << '\n';
+ else
+ std::cerr
+ << "Transferred " << bytes_transferred
+ << " / " << total_buffer_size << " bytes (running total: "
+ << total_sent_bytes_ << " bytes; "
+ << total_sent_packets_ << " packets).\n";
+
+ // Now remove the protocol overhead for the caller, who
+ // doesn't care about them.
+ bytes_transferred -= fcgi::spec::header_length::value;
+ // Check everything was written ok.
+ if (!ec && bytes_transferred != total_buffer_size)
+ ec = ::BOOST_CGI_NAMESPACE::fcgi::error::couldnt_write_complete_packet;
- };
+ return bytes_transferred;
+ }
} // namespace common
namespace fcgi {
typedef
common::basic_client<
- connections::shareable_tcp, ::BOOST_CGI_NAMESPACE::common::fcgi_
+ connections::shareable_tcp, ::BOOST_CGI_NAMESPACE::common::tags::fcgi
>
client;
} // namespace fcgi
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -73,6 +73,9 @@
// (I have no access to a server that supports it)
multiplexing_not_supported,
+ // The client has already been closed.
+ already_closed,
+
// An empty FastCGI packet was read (eg. STDIN or GET_PARAM data has been read).
//empty_packet_read,
@@ -98,6 +101,8 @@
"multiplexed). This isn't handled for now. **FIXME**";
case accepting_on_an_open_request:
return "You called async_accept before closing a request.";
+ case already_closed:
+ return "The client has already been closed.";
case multiplexing_not_supported:
return "Multiplexing connections are not yet supported.";
//case empty_packet_read:
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -154,9 +154,11 @@
impl.service_ = &ps;
}
+ /// Check if the request is still open.
bool is_open(implementation_type& impl)
{
- return !impl.all_done_ && impl.client_.is_open();
+ return impl.request_status_ != common::null
+ && !impl.all_done_ && impl.client_.is_open();
}
/// Close the request.
Added: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/response.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/response.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -0,0 +1,21 @@
+// -- fcgi/response.hpp --
+//
+// Copyright (c) Darren Garvey 2009.
+// 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_FCGI_RESPONSE_HPP_INCLUDED__
+#define CGI_FCGI_RESPONSE_HPP_INCLUDED__
+
+#include "boost/cgi/common/response.hpp"
+
+namespace boost { namespace fcgi {
+
+ typedef ::BOOST_CGI_NAMESPACE::common::response response;
+
+} }
+
+#endif // CGI_FCGI_RESPONSE_HPP_INCLUDED__
+
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/specification.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/specification.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/specification.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -10,6 +10,7 @@
#define CGI_FCGI_SPECIFICATION_HPP_INCLUDED__
#include <boost/cstdint.hpp>
+#include <boost/asio/buffer.hpp>
// NOTE: CamelCase style mimicks the FastCGI specification
// SEE: http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/http/status_code.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/http/status_code.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/http/status_code.hpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -84,9 +84,11 @@
} // namespace http
} // namespace common
- using namespace common::http; // **FIXME**
-
BOOST_CGI_NAMESPACE_END
+namespace boost { namespace http {
+ using namespace ::BOOST_CGI_NAMESPACE::common::http;
+} } // namespace boost::http
+
#endif // CGI_HTTP_STATUS_CODE_HPP_INCLUDED__
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -72,20 +72,35 @@
/// Close the request.
BOOST_CGI_INLINE int
fcgi_request_service::close(
- implementation_type& impl, ::BOOST_CGI_NAMESPACE::common::http::status_code& hsc
+ implementation_type& impl
+ , ::BOOST_CGI_NAMESPACE::common::http::status_code& hsc
, int program_status)
{
- impl.all_done_ = true;
- impl.client_.close(program_status);
- impl.request_status_ = common::closed;
+ boost::system::error_code ec;
+ close(impl, hsc, program_status, ec);
+ detail::throw_error(ec);
return program_status;
}
BOOST_CGI_INLINE int
fcgi_request_service::close(
- implementation_type& impl, ::BOOST_CGI_NAMESPACE::common::http::status_code& hsc
- , int program_status, boost::system::error_code& ec)
+ implementation_type& impl
+ , ::BOOST_CGI_NAMESPACE::common::http::status_code& hsc
+ , int program_status
+ , boost::system::error_code& ec)
{
+ /**
+ * Apache on Windows with mod_fcgid requires that all of the
+ * pending data for the connection is read before the response
+ * is sent.
+ */
+ while(!ec
+ && impl.client_.status() < common::stdin_read
+ && impl.request_status_ != common::loaded)
+ {
+ parse_packet(impl, ec);
+ }
+
impl.all_done_ = true;
impl.client_.close(program_status, ec);
impl.request_status_ = common::closed;
@@ -115,7 +130,6 @@
impl.request_status_ = common::null;
impl.request_role_ = spec_detail::ANY;
impl.all_done_ = false;
-
impl.client_.status_ = common::none_;
impl.client_.request_id_ = -1;
}
@@ -140,7 +154,7 @@
impl.client_.construct(impl, ec);
// Bomb out if the client isn't open here.
- if (!impl.client_.connection_->is_open())
+ if (!impl.client_.connection()->is_open())
return error::client_not_open;
while(!ec)
@@ -198,22 +212,23 @@
&& opts & common::parse_post_only)
{
std::cerr<< "Parsing post vars now.\n";
+
+ if (opts & common::parse_post_only)
+ {
+ while(!ec
+ && impl.client_.status() < common::stdin_read
+ && impl.request_status_ != common::loaded)
+ {
+ parse_packet(impl, ec);
+ }
+ }
+
if (parse_post_vars(impl, ec))
return ec;
}
if (opts & common::parse_cookies_only)
parse_cookie_vars(impl, ec);
- if (opts & common::parse_post_only)
- {
- while(!ec
- && impl.client_.status() < common::stdin_read
- && impl.request_status_ != common::loaded)
- {
- parse_packet(impl, ec);
- }
- }
-
if (ec == error::eof) {
ec = boost::system::error_code();
return ec;
@@ -365,23 +380,10 @@
// clear the header first (might be unneccesary).
impl.header_buf_ = implementation_type::header_buffer_type();
- if (8 != read(*impl.client_.connection_, buffer(impl.header_buf_)
+ if (8 != read(*impl.client_.connection(), buffer(impl.header_buf_)
, boost::asio::transfer_all(), ec) || ec)
return ec;
- //if (ec) return ec;
-
- /*
- std::cerr<< std::endl
- << "[hw] Header details {" << std::endl
- << " RequestId := " << fcgi::spec::get_request_id(impl.header_buf_) << std::endl
- << " FastCGI version := " << fcgi::spec::get_version(impl.header_buf_) << std::endl
- << " Type := " << fcgi::spec::get_type(impl.header_buf_)
- << " (" << fcgi::spec::request_type::to_string(impl.header_buf_) << ")" << std::endl
- << " Content-length := " << fcgi::spec::get_content_length(impl.header_buf_) << std::endl
- << "}" << std::endl;
- */
-
return ec;
}
@@ -422,17 +424,6 @@
}catch(...){
ec = error::abort_request_record_recieved_for_invalid_request;
}
-/*
- connection_type::request_map_type::iterator i
- = connection_->find(id);
-
- if (i == connection_type::request_map_type::iterator())
- {
- return bad_request_id;
- }
-
- //lookup_request(id).abort();
-*/
return ec;
}
@@ -586,7 +577,7 @@
, boost::system::error_code& ec)
{
std::size_t bytes_read
- = read(*impl.client_.connection_, buf
+ = read(*impl.client_.connection(), buf
, boost::asio::transfer_all(), ec);
BOOST_ASSERT(bytes_read == fcgi::spec::get_length(impl.header_buf_)
@@ -659,24 +650,6 @@
BOOST_CGI_NAMESPACE_BEGIN
namespace fcgi {
-/*
- fdetail::request_type&
- get_or_make_request(implementation_type& impl, boost::uint16_t id)
- {
- implementation_type::client_type::connection_type::request_vector_type&
- requests = impl.client_.connection_->requests_;
-
- if (!requests.at(id-1))
- {
- if (requests.size() < (id-1))
- requests.resize(id);
- requests.at(id-1) = fdetail::request_type::create(*impl.service_);
- }
-
- return *requests.at(id-1);
- }
-*/
-
BOOST_CGI_INLINE boost::system::error_code
fcgi_request_service::process_begin_request(
implementation_type& impl, boost::uint16_t id
@@ -693,22 +666,8 @@
// << fcgi::spec::begin_request::get_role(impl.header_buf_) << std::endl;
implementation_type::client_type::connection_type&
- conn = *impl.client_.connection_;
-
- if (conn.get_slot(id, ec))
- { // error
- return ec;
- }
-
- // **FIXME** THIS LEAKS MEMORY!!!!!!!
- //requests.at(id-1)
- //request_type* new_request = new request_type(impl, ec);
-
- //conn.add_request(id, new_request, true, ec);
-
- return ec;//error::multiplexed_request_incoming;
+ conn = *impl.client_.connection();
}
-
return ec;
}
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -324,10 +324,27 @@
/// Get the response as a string.
template<typename T> BOOST_CGI_INLINE
typename basic_response<T>::string_type
- basic_response<T>::str() const
+ basic_response<T>::str(bool include_header) const
{
- return string_type(boost::asio::buffer_cast<const char_type *>(buffer_->data()),
- boost::asio::buffer_size(buffer_->data()));
+ string_type body;
+ if (include_header)
+ {
+ typedef std::vector<string_type>::const_iterator iter_t;
+ for (
+ iter_t iter(headers_.begin()), end(headers_.end());
+ iter != end;
+ ++iter
+ ) {
+ body += *iter;
+ }
+ if (!headers_terminated_) body += "\r\n";
+ }
+
+ body += string_type(
+ boost::asio::buffer_cast<const char_type *>(buffer_->data()),
+ boost::asio::buffer_size(buffer_->data()));
+
+ return body;
}
@@ -415,19 +432,23 @@
{
BOOST_CGI_ADD_DEFAULT_HEADER;
- BOOST_ASSERT((headers_[0].length() > 13 && "Content-type header not found"));
-
- headers_[0].insert(headers_[0].length()-2, "; charset: " + charset_);
-
// Terminate the headers.
if (!headers_terminated_)
headers_.push_back("\r\n");
- //{ Construct a ConstBufferSequence out of the headers we have.
- typedef typename std::vector<string_type>::iterator iter;
- for (iter i(headers_.begin()), e(headers_.end()); i != e; ++i)
- {
- headers.push_back(common::buffer(*i));
+ typedef std::vector<string_type>::iterator iter_t;
+ for (
+ iter_t iter(headers_.begin()), end(headers_.end());
+ iter != end;
+ ++iter
+ )
+ {
+ boost::cgi::common::name type(iter->substr(0, 12).c_str());
+ if (type == "Content-type")
+ iter->insert(iter->length()-2, "; charset: " + charset_);
+
+ //{ Construct a ConstBufferSequence out of the headers we have.
+ headers.push_back(common::buffer(*iter));
}
//}
@@ -483,7 +504,7 @@
operator<< (BOOST_CGI_NAMESPACE::common::basic_response<CharT>& resp
, BOOST_CGI_NAMESPACE::common::charset_header<CharT> const& hdr)
{
- resp.charset() = hdr.content;
+ resp.charset(hdr.content);
return resp;
}
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.suo
==============================================================================
Binary files. No diff available.
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -163,6 +163,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="copy "$(TargetPath)" "c:\code\c++\boost.cgi\cgi-bin\$(TargetName)""
/>
</Configuration>
</Configurations>
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -203,6 +203,8 @@
}
}
+ std::cin.get();
+
return ret;
}catch(boost::system::system_error const& se){
@@ -217,5 +219,7 @@
std::cerr<< "[fcgi] Uncaught exception!" << std::endl;
return -3;
}
+ std::cerr<< "Press enter to continue." << std::endl;
+ std::cin.get();
}
//]
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/hello_world/main.cpp 2009-12-02 22:43:00 EST (Wed, 02 Dec 2009)
@@ -31,6 +31,7 @@
// the response text.
req.load(parse_env);
resp<< content_type("text/plain")
+ << header("X-Protocol", "FastCGI")
<< "Hello there, universe.";
return commit(req, resp, 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