pion  5.0.6
response_writer.hpp
1 // ---------------------------------------------------------------------
2 // pion: a Boost C++ framework for building lightweight HTTP interfaces
3 // ---------------------------------------------------------------------
4 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #ifndef __PION_HTTP_RESPONSE_WRITER_HEADER__
11 #define __PION_HTTP_RESPONSE_WRITER_HEADER__
12 
13 #include <boost/asio.hpp>
14 #include <boost/bind.hpp>
15 #include <boost/noncopyable.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include <boost/enable_shared_from_this.hpp>
18 #include <pion/config.hpp>
19 #include <pion/http/writer.hpp>
20 #include <pion/http/request.hpp>
21 #include <pion/http/response.hpp>
22 
23 
24 namespace pion { // begin namespace pion
25 namespace http { // begin namespace http
26 
27 
31 class PION_API response_writer :
32  public http::writer,
33  public boost::enable_shared_from_this<response_writer>
34 {
35 public:
36 
38  virtual ~response_writer() {}
39 
50  static inline boost::shared_ptr<response_writer> create(const tcp::connection_ptr& tcp_conn,
51  const http::response_ptr& http_response_ptr,
53  {
54  return boost::shared_ptr<response_writer>(new response_writer(tcp_conn, http_response_ptr, handler));
55  }
56 
67  static inline boost::shared_ptr<response_writer> create(const tcp::connection_ptr& tcp_conn,
68  const http::request& http_request,
70  {
71  return boost::shared_ptr<response_writer>(new response_writer(tcp_conn, http_request, handler));
72  }
73 
75  inline http::response& get_response(void) { return *m_http_response; }
76 
77 
78 protected:
79 
87  response_writer(const tcp::connection_ptr& tcp_conn, const http::response_ptr& http_response_ptr,
88  finished_handler_t handler)
89  : http::writer(tcp_conn, handler), m_http_response(http_response_ptr)
90  {
91  set_logger(PION_GET_LOGGER("pion.http.response_writer"));
92  // tell the http::writer base class whether or not the client supports chunks
93  supports_chunked_messages(m_http_response->get_chunks_supported());
94  // check if we should initialize the payload content using
95  // the response's content buffer
96  if (m_http_response->get_content_length() > 0
97  && m_http_response->get_content() != NULL
98  && m_http_response->get_content()[0] != '\0')
99  {
100  write_no_copy(m_http_response->get_content(), m_http_response->get_content_length());
101  }
102  }
103 
111  response_writer(const tcp::connection_ptr& tcp_conn, const http::request& http_request,
112  finished_handler_t handler)
113  : http::writer(tcp_conn, handler), m_http_response(new http::response(http_request))
114  {
115  set_logger(PION_GET_LOGGER("pion.http.response_writer"));
116  // tell the http::writer base class whether or not the client supports chunks
117  supports_chunked_messages(m_http_response->get_chunks_supported());
118  }
119 
120 
127  if (get_content_length() > 0)
128  m_http_response->set_content_length(get_content_length());
129  m_http_response->prepare_buffers_for_send(write_buffers,
130  get_connection()->get_keep_alive(),
131  sending_chunked_message());
132  }
133 
136  return boost::bind(&response_writer::handle_write, shared_from_this(),
137  boost::asio::placeholders::error,
138  boost::asio::placeholders::bytes_transferred);
139  }
140 
147  virtual void handle_write(const boost::system::error_code& write_error,
148  std::size_t bytes_written)
149  {
150  logger log_ptr(get_logger());
151  if (!write_error) {
152  // response sent OK
153  if (sending_chunked_message()) {
154  PION_LOG_DEBUG(log_ptr, "Sent HTTP response chunk of " << bytes_written << " bytes");
155  } else {
156  PION_LOG_DEBUG(log_ptr, "Sent HTTP response of " << bytes_written << " bytes ("
157  << (get_connection()->get_keep_alive() ? "keeping alive)" : "closing)"));
158  }
159  }
160  finished_writing(write_error);
161  }
162 
163 
164 private:
165 
167  http::response_ptr m_http_response;
168 
170  std::string m_response_line;
171 };
172 
173 
175 typedef boost::shared_ptr<response_writer> response_writer_ptr;
176 
177 
179 template <typename T>
180 const response_writer_ptr& operator<<(const response_writer_ptr& writer, const T& data) {
181  writer->write(data);
182  return writer;
183 }
184 
185 inline response_writer_ptr& operator<<(response_writer_ptr& writer, std::ostream& (*iomanip)(std::ostream&)) {
186  writer->write(iomanip);
187  return writer;
188 }
189 
190 } // end namespace http
191 } // end namespace pion
192 
193 #endif
virtual void prepare_buffers_for_send(http::message::write_buffers_t &write_buffers)
virtual ~response_writer()
default destructor
boost::function2< void, const boost::system::error_code &, std::size_t > write_handler_t
data type for a function that handles write operations
Definition: writer.hpp:43
response_writer(const tcp::connection_ptr &tcp_conn, const http::request &http_request, finished_handler_t handler)
static boost::shared_ptr< response_writer > create(const tcp::connection_ptr &tcp_conn, const http::response_ptr &http_response_ptr, finished_handler_t handler=finished_handler_t())
boost::function1< void, const boost::system::error_code & > finished_handler_t
function called after the HTTP message has been sent
Definition: writer.hpp:40
response_writer(const tcp::connection_ptr &tcp_conn, const http::response_ptr &http_response_ptr, finished_handler_t handler)
virtual void handle_write(const boost::system::error_code &write_error, std::size_t bytes_written)
http::response & get_response(void)
returns a non-const reference to the response that will be sent
static boost::shared_ptr< response_writer > create(const tcp::connection_ptr &tcp_conn, const http::request &http_request, finished_handler_t handler=finished_handler_t())
std::vector< boost::asio::const_buffer > write_buffers_t
data type for I/O write buffers (these wrap existing data to be sent)
Definition: message.hpp:61
virtual write_handler_t bind_to_write_handler(void)
returns a function bound to http::writer::handle_write()