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             // encountered error sending response
00152             getTCPConnection()->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);   // make sure it will get closed
00153             PION_LOG_WARN(log_ptr, "Unable to send HTTP response (" << write_error.message() << ')');
00154         } else {
00155             // response sent OK
00156             if (sendingChunkedMessage()) {
00157                 PION_LOG_DEBUG(log_ptr, "Sent HTTP response chunk of " << bytes_written << " bytes");
00158             } else {
00159                 PION_LOG_DEBUG(log_ptr, "Sent HTTP response of " << bytes_written << " bytes ("
00160                                << (getTCPConnection()->getKeepAlive() ? "keeping alive)" : "closing)"));
00161             }
00162         }
00163         finishedWriting();
00164     }
00165 
00166     
00167 private:
00168     
00170     HTTPResponsePtr         m_http_response;
00171     
00173     std::string             m_response_line;
00174 };
00175 
00176 
00178 typedef boost::shared_ptr<HTTPResponseWriter>   HTTPResponseWriterPtr;
00179 
00180 
00182 template <typename T>
00183 HTTPResponseWriterPtr& operator<<(HTTPResponseWriterPtr& writer, const T& data) {
00184     writer->write(data);
00185     return writer;
00186 }
00187 
00188 
00189 }   // end namespace net
00190 }   // end namespace pion
00191 
00192 #endif

Generated on Fri Apr 30 14:48:53 2010 for pion-net by  doxygen 1.4.7