Add gzip compressing

This commit is contained in:
antao 2018-09-03 10:56:11 +08:00
parent 44bdc8ecbc
commit 790867d1e3
7 changed files with 120 additions and 33 deletions

View File

@ -48,7 +48,8 @@ if(OpenSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
message(STATUS "openssl inc path:" ${OPENSSL_INCLUDE_DIR})
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
find_package(Boost)
if(Boost_FOUND)
# add_definitions(-DUSE_BOOST)

View File

@ -1,4 +1,4 @@
link_libraries(drogon trantor uuid pthread jsoncpp dl)
link_libraries(drogon trantor uuid pthread jsoncpp dl z)
if(OpenSSL_FOUND)
link_libraries(ssl crypto)
endif()

View File

@ -94,6 +94,8 @@ namespace drogon
virtual void setContentTypeCode(uint8_t type)=0;
virtual uint8_t getContentTypeCode()=0;
virtual std::string getHeader(const std::string& key) const =0;
virtual void addHeader(const std::string& key, const std::string& value)=0;
@ -112,7 +114,8 @@ namespace drogon
virtual void clear()=0;
virtual std::string getBody() const=0;
virtual const std::string & getBody() const=0;
virtual std::string & getBody() = 0;
virtual const std::shared_ptr<Json::Value> getJsonObject() const =0;
static HttpResponsePtr newHttpResponse();

View File

@ -26,7 +26,11 @@ namespace drogon{
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
std::string base64_decode(std::string const& encoded_string);
std::string urlDecode(const std::string& szToDecode);
// std::string base64Encode(char *in_str, int in_len)
int gzcompress(const char *data, const size_t ndata,
char *zdata, size_t *nzdata);
int gzdecompress(const char *zdata, const size_t nzdata,
char *data, size_t *ndata);
}

View File

@ -110,7 +110,10 @@ namespace drogon
_contentType=type;
setContentType(web_content_type_to_string(type));
}
virtual uint8_t getContentTypeCode() override
{
return _contentType;
}
// virtual uint8_t contentTypeCode() override
// {
// return _contentType;
@ -222,11 +225,14 @@ namespace drogon
// receiveTime_ = t;
// }
virtual std::string getBody() const override
virtual const std::string & getBody() const override
{
return _body;
}
virtual std::string & getBody() override
{
return _body;
}
void swap(HttpResponseImpl &that)
{
_headers.swap(that._headers);

View File

@ -28,6 +28,7 @@
#include "HttpContext.h"
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
#include <drogon/utils/Utilities.h>
#include <functional>
using namespace std::placeholders;
@ -162,11 +163,31 @@ void HttpServer::onRequest(const TcpConnectionPtr& conn, const HttpRequestPtr& r
if(!response)
return;
response->setCloseConnection(_close);
if(response->getContentTypeCode()<CT_APPLICATION_OCTET_STREAM&&
response->getBody().length()>4096&&
req->getHeader("Accept-Encoding").find("gzip")!=std::string::npos)
{
//use gzip
LOG_TRACE<<"Use gzip to compress the body";
char zbuf[response->getBody().length()];
size_t zlen;
if(gzcompress(response->getBody().data(),
response->getBody().length(),
zbuf,&zlen)>=0)
{
response->setBody(std::string(zbuf,zlen));
response->addHeader("Content-Encoding","gzip");
}
}
std::dynamic_pointer_cast<HttpResponseImpl>(response)->appendToBuffer(&buf);
conn->send(std::move(buf));
if (_close) {
conn->shutdown();
}
});

View File

@ -1,12 +1,7 @@
#include <drogon/utils/Utilities.h>
#include <drogon/config.h>
#include <string.h>
//#ifdef USE_OPENSSL
//#include <openssl/sha.h>
////#include <openssl/pem.h>
////#include <openssl/bio.h>
////#include <openssl/evp.h>
//#endif
#include <zlib.h>
namespace drogon{
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@ -227,24 +222,81 @@ namespace drogon{
return result;
}
// std::string base64Encode(char *in_str, int in_len)
// {
// BIO *b64, *bio;
// BUF_MEM *bptr = NULL;
// size_t size = 0;
//
// assert(in_str);
//
// b64 = BIO_new(BIO_f_base64());
// bio = BIO_new(BIO_s_mem());
// bio = BIO_push(b64, bio);
//
// BIO_write(bio, in_str, in_len);
// BIO_flush(bio);
//
// BIO_get_mem_ptr(bio, &bptr);
// std::string ret(bptr->data,bptr->length);
// BIO_free_all(bio);
// return ret;
// }
/* Compress gzip data */
/* data 原数据 ndata 原数据长度 zdata 压缩后数据 nzdata 压缩后长度 */
int gzcompress(const char *data, const size_t ndata,
char *zdata, size_t *nzdata)
{
z_stream c_stream;
int err = 0;
if(data && ndata > 0) {
c_stream.zalloc = NULL;
c_stream.zfree = NULL;
c_stream.opaque = NULL;
//只有设置为MAX_WBITS + 16才能在在压缩文本中带header和trailer
if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) return-1;
c_stream.next_in = (Bytef *)data;
c_stream.avail_in = ndata;
c_stream.next_out = (Bytef *)zdata;
c_stream.avail_out = *nzdata;
while(c_stream.avail_in != 0 && c_stream.total_out < *nzdata) {
if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return-1;
}
if(c_stream.avail_in != 0) return c_stream.avail_in;
for(;;) {
if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;
if(err != Z_OK) return -1;
}
if(deflateEnd(&c_stream) != Z_OK) return -1;
*nzdata = c_stream.total_out;
return 0;
}
return -1;
}
/* Uncompress gzip data */
/* zdata 数据 nzdata 原数据长度 data 解压后数据 ndata 解压后长度 */
int gzdecompress(const char *zdata, const size_t nzdata,
char *data, size_t *ndata)
{
int err = 0;
z_stream d_stream = {0}; /* decompression stream */
static char dummy_head[2] = {
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
d_stream.zalloc = NULL;
d_stream.zfree = NULL;
d_stream.opaque = NULL;
d_stream.next_in = (Bytef *)zdata;
d_stream.avail_in = 0;
d_stream.next_out = (Bytef *)data;
//只有设置为MAX_WBITS + 16才能在解压带header和trailer的文本
if(inflateInit2(&d_stream, MAX_WBITS + 16) != Z_OK) return-1;
//if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
while(d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK) {
if(err == Z_DATA_ERROR) {
d_stream.next_in = (Bytef*) dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) {
return -1;
}
}else
return -1;
}
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
}