# 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