mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-12-02 03:38:03 +08:00
Add gzip compressing
This commit is contained in:
parent
44bdc8ecbc
commit
790867d1e3
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user