Permalink
Browse files

Add support to return gzip'd content from built-in http server.

gzipCompress should be moved to a more global location.
  • Loading branch information...
1 parent c71ee01 commit 47c96d53b6e1d903fc0b69076f26f80a203cfd9c @dblain dblain committed Apr 9, 2012
@@ -264,12 +264,37 @@ long HTTPRequest::SendResponse( void )
}
// ----------------------------------------------------------------------
+
+ int nContentLen = m_response.buffer().length();
+
+ QBuffer *pBuffer = &m_response;
+
+ // ----------------------------------------------------------------------
+ // Should we try to return data gzip'd?
+ // ----------------------------------------------------------------------
+
+ QBuffer compBuffer;
+
+ if (( nContentLen > 0 ) && m_mapHeaders[ "accept-encoding" ].contains( "gzip" ))
+ {
+ QByteArray compressed = gzipCompress( m_response.buffer() );
+ compBuffer.setData( compressed );
+
+ if (compBuffer.buffer().length() > 0)
+ {
+ pBuffer = &compBuffer;
+
+ m_mapRespHeaders[ "Content-Encoding" ] = "gzip";
+ }
+ }
+
+ // ----------------------------------------------------------------------
// Write out Header.
// ----------------------------------------------------------------------
- const QByteArray &buffer = m_response.buffer();
+ nContentLen = pBuffer->buffer().length();
- QString rHeader = BuildHeader( buffer.length() );
+ QString rHeader = BuildHeader( nContentLen );
QByteArray sHeader = rHeader.toUtf8();
nBytes = WriteBlockDirect( sHeader.constData(), sHeader.length() );
@@ -278,9 +303,9 @@ long HTTPRequest::SendResponse( void )
// Write out Response buffer.
// ----------------------------------------------------------------------
- if (( m_eType != RequestTypeHead ) && ( buffer.length() > 0 ))
+ if (( m_eType != RequestTypeHead ) && ( nContentLen > 0 ))
{
- nBytes += SendData( &m_response, 0, m_response.size() );
+ nBytes += SendData( pBuffer, 0, nContentLen );
}
// ----------------------------------------------------------------------
@@ -455,8 +480,15 @@ long HTTPRequest::SendResponseFile( QString sFileName )
qint64 HTTPRequest::SendData( QIODevice *pDevice, qint64 llStart, qint64 llBytes )
{
+ bool bShouldClose = false;
qint64 sent = 0;
+ if (!pDevice->isOpen())
+ {
+ pDevice->open( QIODevice::ReadOnly );
+ bShouldClose = true;
+ }
+
// ----------------------------------------------------------------------
// Set out file position to requested start location.
// ----------------------------------------------------------------------
@@ -487,6 +519,9 @@ qint64 HTTPRequest::SendData( QIODevice *pDevice, qint64 llStart, qint64 llBytes
}
}
+ if (bShouldClose)
+ pDevice->close();
+
return sent;
}
@@ -1689,3 +1724,4 @@ bool BufferedSocketDeviceRequest::IsBlocking()
return false;
}
+
@@ -34,6 +34,8 @@
#include <ifaddrs.h>
#endif
+#include "zlib.h"
+
/////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////
@@ -246,3 +248,66 @@ void AddSecondsToTaskTime( TaskTime &t, long nSecs )
{
t.tv_sec += nSecs;
}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+/////////////////////////////////////////////////////////////////////////////
+
+QByteArray gzipCompress( const QByteArray &data )
+{
+ if (data.length() == 0)
+ return QByteArray();
+
+ static const int CHUNK_SIZE = 1024;
+ char out[ CHUNK_SIZE ];
+
+ // allocate inflate state
+ z_stream strm;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = data.length();
+ strm.next_in = (Bytef*)(data.data());
+
+ int ret = deflateInit2( &strm,
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ 15 + 16,
+ 8,
+ Z_DEFAULT_STRATEGY ); // gzip encoding
+ if (ret != Z_OK)
+ return QByteArray();
+
+ QByteArray result;
+
+ // run deflate()
+ do
+ {
+ strm.avail_out = CHUNK_SIZE;
+ strm.next_out = (Bytef*)(out);
+
+ ret = deflate(&strm, Z_FINISH);
+
+ Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
+
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR; // and fall through
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ (void)deflateEnd(&strm);
+ return QByteArray();
+ }
+
+ result.append( out, CHUNK_SIZE - strm.avail_out );
+ }
+ while (strm.avail_out == 0);
+
+ // clean up and return
+
+ deflateEnd(&strm);
+
+ return result;
+}
@@ -139,4 +139,6 @@ bool operator== ( TaskTime t1, TaskTime t2 );
void AddMicroSecToTaskTime( TaskTime &t, suseconds_t uSecs );
void AddSecondsToTaskTime ( TaskTime &t, long nSecs );
+QByteArray gzipCompress( const QByteArray &data );
+
#endif

0 comments on commit 47c96d5

Please sign in to comment.