pion-net
4.0.9
|
00001 // ------------------------------------------------------------------ 00002 // pion-net: a C++ framework for building lightweight HTTP interfaces 00003 // ------------------------------------------------------------------ 00004 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.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_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 { // begin namespace pion 00025 namespace net { // begin namespace net (Pion Network Library) 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 // tell the HTTPWriter base class whether or not the client supports chunks 00092 supportsChunkedMessages(m_http_response->getChunksSupported()); 00093 // check if we should initialize the payload content using 00094 // the response's content buffer 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 // tell the HTTPWriter base class whether or not the client supports chunks 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 // response sent OK 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 } // end namespace net 00186 } // end namespace pion 00187 00188 #endif