00001
00002
00003
00004
00005
00006
00007
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 {
00025 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
00093 supports_chunked_messages(m_http_response->get_chunks_supported());
00094
00095
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
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
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 }
00191 }
00192
00193 #endif