00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_HTTPRESPONSEWRITER_HEADER__
00011 #define __PION_HTTPRESPONSEWRITER_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/PionConfig.hpp>
00019 #include <pion/net/HTTPWriter.hpp>
00020 #include <pion/net/HTTPRequest.hpp>
00021 #include <pion/net/HTTPResponse.hpp>
00022
00023
00024 namespace pion {
00025 namespace net {
00026
00030 class PION_NET_API HTTPResponseWriter :
00031 public HTTPWriter,
00032 public boost::enable_shared_from_this<HTTPResponseWriter>
00033 {
00034 public:
00035
00037 virtual ~HTTPResponseWriter() {}
00038
00049 static inline boost::shared_ptr<HTTPResponseWriter> create(TCPConnectionPtr& tcp_conn,
00050 HTTPResponsePtr& http_response,
00051 FinishedHandler handler = FinishedHandler())
00052 {
00053 return boost::shared_ptr<HTTPResponseWriter>(new HTTPResponseWriter(tcp_conn, http_response, handler));
00054 }
00055
00066 static inline boost::shared_ptr<HTTPResponseWriter> create(TCPConnectionPtr& tcp_conn,
00067 const HTTPRequest& http_request,
00068 FinishedHandler handler = FinishedHandler())
00069 {
00070 return boost::shared_ptr<HTTPResponseWriter>(new HTTPResponseWriter(tcp_conn, http_request, handler));
00071 }
00072
00074 inline HTTPResponse& getResponse(void) { return *m_http_response; }
00075
00076
00077 protected:
00078
00086 HTTPResponseWriter(TCPConnectionPtr& tcp_conn, HTTPResponsePtr& http_response,
00087 FinishedHandler handler)
00088 : HTTPWriter(tcp_conn, handler), m_http_response(http_response)
00089 {
00090 setLogger(PION_GET_LOGGER("pion.net.HTTPResponseWriter"));
00091
00092 supportsChunkedMessages(m_http_response->getChunksSupported());
00093
00094
00095 if (http_response->getContentLength() > 0
00096 && http_response->getContent() != NULL
00097 && http_response->getContent()[0] != '\0')
00098 {
00099 writeNoCopy(http_response->getContent(), http_response->getContentLength());
00100 }
00101 }
00102
00110 HTTPResponseWriter(TCPConnectionPtr& tcp_conn, const HTTPRequest& http_request,
00111 FinishedHandler handler)
00112 : HTTPWriter(tcp_conn, handler), m_http_response(new HTTPResponse(http_request))
00113 {
00114 setLogger(PION_GET_LOGGER("pion.net.HTTPResponseWriter"));
00115
00116 supportsChunkedMessages(m_http_response->getChunksSupported());
00117 }
00118
00119
00125 virtual void prepareBuffersForSend(HTTPMessage::WriteBuffers& write_buffers) {
00126 if (getContentLength() > 0)
00127 m_http_response->setContentLength(getContentLength());
00128 m_http_response->prepareBuffersForSend(write_buffers,
00129 getTCPConnection()->getKeepAlive(),
00130 sendingChunkedMessage());
00131 }
00132
00134 virtual WriteHandler bindToWriteHandler(void) {
00135 return boost::bind(&HTTPResponseWriter::handleWrite, shared_from_this(),
00136 boost::asio::placeholders::error,
00137 boost::asio::placeholders::bytes_transferred);
00138 }
00139
00146 virtual void handleWrite(const boost::system::error_code& write_error,
00147 std::size_t bytes_written)
00148 {
00149 PionLogger log_ptr(getLogger());
00150 if (!write_error) {
00151
00152 if (sendingChunkedMessage()) {
00153 PION_LOG_DEBUG(log_ptr, "Sent HTTP response chunk of " << bytes_written << " bytes");
00154 } else {
00155 PION_LOG_DEBUG(log_ptr, "Sent HTTP response of " << bytes_written << " bytes ("
00156 << (getTCPConnection()->getKeepAlive() ? "keeping alive)" : "closing)"));
00157 }
00158 }
00159 finishedWriting(write_error);
00160 }
00161
00162
00163 private:
00164
00166 HTTPResponsePtr m_http_response;
00167
00169 std::string m_response_line;
00170 };
00171
00172
00174 typedef boost::shared_ptr<HTTPResponseWriter> HTTPResponseWriterPtr;
00175
00176
00178 template <typename T>
00179 const HTTPResponseWriterPtr& operator<<(const HTTPResponseWriterPtr& writer, const T& data) {
00180 writer->write(data);
00181 return writer;
00182 }
00183
00184
00185 }
00186 }
00187
00188 #endif