pion-net  4.0.9
net/include/pion/net/HTTPResponseWriter.hpp
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