pion
5.0.6
|
00001 // --------------------------------------------------------------------- 00002 // pion: a Boost C++ framework for building lightweight HTTP interfaces 00003 // --------------------------------------------------------------------- 00004 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion) 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