- Main Page
- Classes
- Files

- File List

# include/pion/http/response_writer.hpp

    00001 // ---------------------------------------------------------------------
    00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
    00003 // ---------------------------------------------------------------------
    00004 // Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #ifndef __PION_HTTP_RESPONSE_WRITER_HEADER__
    00011 #define __PION_HTTP_RESPONSE_WRITER_HEADER__
    00012
    00013 #include <boost/asio.hpp>
    00014 #include <boost/bind.hpp>
    00015 #include <boost/noncopyable.hpp>
    00016 #include <boost/shared_ptr.hpp>
    00017 #include <boost/enable_shared_from_this.hpp>
    00018 #include <pion/config.hpp>
    00019 #include <pion/http/writer.hpp>
    00020 #include <pion/http/request.hpp>
    00021 #include <pion/http/response.hpp>
    00022
    00023
    00024 namespace pion {    // begin namespace pion
    00025 namespace http {    // begin namespace http
    00026
    00027
    00031 class PION_API response_writer :
    00032     public http::writer,
    00033     public boost::enable_shared_from_this<response_writer>
    00034 {
    00035 public:
    00036
    00038     virtual ~response_writer() {}
    00039
    00050     static inline boost::shared_ptr<response_writer> create(tcp::connection_ptr& tcp_conn,
    00051                                                                http::response_ptr& http_response_ptr,
    00052                                                                finished_handler_t handler = finished_handler_t())
    00053     {
    00054         return boost::shared_ptr<response_writer>(new response_writer(tcp_conn, http_response_ptr, handler));
    00055     }
    00056
    00067     static inline boost::shared_ptr<response_writer> create(tcp::connection_ptr& tcp_conn,
    00068                                                                const http::request& http_request,
    00069                                                                finished_handler_t handler = finished_handler_t())
    00070     {
    00071         return boost::shared_ptr<response_writer>(new response_writer(tcp_conn, http_request, handler));
    00072     }
    00073
    00075     inline http::response& get_response(void) { return *m_http_response; }
    00076
    00077
    00078 protected:
    00079
    00087     response_writer(tcp::connection_ptr& tcp_conn, http::response_ptr& http_response_ptr,
    00088                        finished_handler_t handler)
    00089         : http::writer(tcp_conn, handler), m_http_response(http_response_ptr)
    00090     {
    00091         set_logger(PION_GET_LOGGER("pion.http.response_writer"));
    00092         // tell the http::writer base class whether or not the client supports chunks
    00093         supports_chunked_messages(m_http_response->get_chunks_supported());
    00094         // check if we should initialize the payload content using
    00095         // the response's content buffer
    00096         if (m_http_response->get_content_length() > 0
    00097             && m_http_response->get_content() != NULL
    00098             && m_http_response->get_content()[0] != '\0')
    00099         {
    00100             write_no_copy(m_http_response->get_content(), m_http_response->get_content_length());
    00101         }
    00102     }
    00103
    00111     response_writer(tcp::connection_ptr& tcp_conn, const http::request& http_request,
    00112                        finished_handler_t handler)
    00113         : http::writer(tcp_conn, handler), m_http_response(new http::response(http_request))
    00114     {
    00115         set_logger(PION_GET_LOGGER("pion.http.response_writer"));
    00116         // tell the http::writer base class whether or not the client supports chunks
    00117         supports_chunked_messages(m_http_response->get_chunks_supported());
    00118     }
    00119
    00120
    00126     virtual void prepare_buffers_for_send(http::message::write_buffers_t& write_buffers) {
    00127         if (get_content_length() > 0)
    00128             m_http_response->set_content_length(get_content_length());
    00129         m_http_response->prepare_buffers_for_send(write_buffers,
    00130                                                get_connection()->get_keep_alive(),
    00131                                                sending_chunked_message());
    00132     }
    00133
    00135     virtual write_handler_t bind_to_write_handler(void) {
    00136         return boost::bind(&response_writer::handle_write, shared_from_this(),
    00137                            boost::asio::placeholders::error,
    00138                            boost::asio::placeholders::bytes_transferred);
    00139     }
    00140
    00147     virtual void handle_write(const boost::system::error_code& write_error,
    00148                              std::size_t bytes_written)
    00149     {
    00150         logger log_ptr(get_logger());
    00151         if (!write_error) {
    00152             // response sent OK
    00153             if (sending_chunked_message()) {
    00154                 PION_LOG_DEBUG(log_ptr, "Sent HTTP response chunk of " << bytes_written << " bytes");
    00155             } else {
    00156                 PION_LOG_DEBUG(log_ptr, "Sent HTTP response of " << bytes_written << " bytes ("
    00157                                << (get_connection()->get_keep_alive() ? "keeping alive)" : "closing)"));
    00158             }
    00159         }
    00160         finished_writing(write_error);
    00161     }
    00162
    00163
    00164 private:
    00165
    00167     http::response_ptr      m_http_response;
    00168
    00170     std::string             m_response_line;
    00171 };
    00172
    00173
    00175 typedef boost::shared_ptr<response_writer>   response_writer_ptr;
    00176
    00177
    00179 template <typename T>
    00180 const response_writer_ptr& operator<<(const response_writer_ptr& writer, const T& data) {
    00181     writer->write(data);
    00182     return writer;
    00183 }
    00184
    00185 inline response_writer_ptr& operator<<(response_writer_ptr& writer, std::ostream& (*iomanip)(std::ostream&)) {
    00186     writer->write(iomanip);
    00187     return writer;
    00188 }
    00189
    00190 }   // end namespace http
    00191 }   // end namespace pion
    00192
    00193 #endif