1 /** @file httpwriter.hxx 2 * 3 * @copyright (C) 2016 4 * @date 2016.05.26 5 * @version 1.0.0 6 * @author amir zamani <azadkuh@live.com> 7 * 8 */ 9 10 #ifndef __QHTTP_HTTPWRITER_HXX__ 11 #define __QHTTP_HTTPWRITER_HXX__ 12 13 #include "qhttpbase.hpp" 14 15 /////////////////////////////////////////////////////////////////////////////// 16 namespace qhttp { 17 namespace details { 18 /////////////////////////////////////////////////////////////////////////////// 19 20 // usage in client::QHttpRequest, server::QHttpResponse 21 template<class TBase, class TImpl> 22 class HttpWriter : public TBase 23 { 24 public: addHeader(const QByteArray & field,const QByteArray & value)25 bool addHeader(const QByteArray &field, const QByteArray &value) { 26 if ( ifinished ) 27 return false; 28 29 TBase::iheaders.insert(field.toLower(), value); 30 return true; 31 } 32 writeHeader(const QByteArray & field,const QByteArray & value)33 bool writeHeader(const QByteArray& field, const QByteArray& value) { 34 if ( ifinished ) 35 return false; 36 37 QByteArray buffer = QByteArray(field) 38 .append(": ") 39 .append(value) 40 .append("\r\n"); 41 42 isocket.writeRaw(buffer); 43 return true; 44 } 45 writeData(const QByteArray & data)46 bool writeData(const QByteArray& data) { 47 if ( ifinished ) 48 return false; 49 50 ensureWritingHeaders(); 51 isocket.writeRaw(data); 52 return true; 53 } 54 endPacket(const QByteArray & data)55 bool endPacket(const QByteArray& data) { 56 if ( !writeData(data) ) 57 return false; 58 59 isocket.flush(); 60 ifinished = true; 61 return true; 62 } 63 ensureWritingHeaders()64 void ensureWritingHeaders() { 65 if ( ifinished || iheaderWritten ) 66 return; 67 68 TImpl* me = static_cast<TImpl*>(this); 69 isocket.writeRaw(me->makeTitle()); 70 writeHeaders(); 71 72 iheaderWritten = true; 73 } 74 writeHeaders(bool doFlush=false)75 void writeHeaders(bool doFlush = false) { 76 if ( ifinished || iheaderWritten ) 77 return; 78 79 if ( TBase::iheaders.keyHasValue("connection", "keep-alive") ) 80 ikeepAlive = true; 81 else 82 TBase::iheaders.insert("connection", "close"); 83 84 TImpl* me = static_cast<TImpl*>(this); 85 me->prepareHeadersToWrite(); 86 87 TBase::iheaders.forEach([this](const auto& cit) { 88 this->writeHeader(cit.key(), cit.value()); 89 }); 90 91 isocket.writeRaw("\r\n"); 92 if ( doFlush ) 93 isocket.flush(); 94 } 95 96 public: 97 QSocket isocket; 98 99 bool ifinished = false; 100 bool iheaderWritten = false; 101 bool ikeepAlive = false; 102 }; 103 104 105 /////////////////////////////////////////////////////////////////////////////// 106 } // namespace details 107 } // namespace qhttp 108 /////////////////////////////////////////////////////////////////////////////// 109 #endif // __QHTTP_HTTPWRITER_HXX__ 110