Add an option to disable GZIP.

master
Chunting Gu 6 years ago
parent 88f5ae3c91
commit 2a868c4dc1

@ -23,6 +23,7 @@ set(WEBCC_ENABLE_LOG 1 CACHE STRING "Enable logging? (1:Yes, 0:No)")
set(WEBCC_LOG_LEVEL 2 CACHE STRING "Log level (0:VERB, 1:INFO, 2:WARN, 3:ERRO or 4:FATA)") set(WEBCC_LOG_LEVEL 2 CACHE STRING "Log level (0:VERB, 1:INFO, 2:WARN, 3:ERRO or 4:FATA)")
set(WEBCC_ENABLE_SSL 0 CACHE STRING "Enable SSL/HTTPS (need OpenSSL)? (1:Yes, 0:No)") set(WEBCC_ENABLE_SSL 0 CACHE STRING "Enable SSL/HTTPS (need OpenSSL)? (1:Yes, 0:No)")
set(WEBCC_ENABLE_GZIP 0 CACHE STRING "Enable gzip compression (need Zlib)? (1:Yes, 0:No)")
if(WEBCC_ENABLE_UNITTEST) if(WEBCC_ENABLE_UNITTEST)
enable_testing() enable_testing()
@ -111,18 +112,20 @@ endif()
include_directories(${THIRD_PARTY_DIR}/src) include_directories(${THIRD_PARTY_DIR}/src)
# For using zlib on Windows. if(WEBCC_ENABLE_GZIP)
if(WIN32) # For using zlib on Windows.
add_subdirectory(${THIRD_PARTY_DIR}/src/zlib) if(WIN32)
add_subdirectory(${THIRD_PARTY_DIR}/src/zlib)
include_directories(${THIRD_PARTY_DIR}/src/zlib) include_directories(${THIRD_PARTY_DIR}/src/zlib)
# For including CMake generated zconf.h. # For including CMake generated zconf.h.
include_directories(${PROJECT_BINARY_DIR}/third_party/src/zlib) include_directories(${PROJECT_BINARY_DIR}/third_party/src/zlib)
else() else()
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
if(ZLIB_FOUND) if(ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIRS}) include_directories(${ZLIB_INCLUDE_DIRS})
endif()
endif() endif()
endif() endif()

@ -10,14 +10,15 @@ set(AT_TARGET_NAME webcc_autotest)
set(AT_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}") set(AT_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}")
if(WEBCC_ENABLE_SSL) if(WEBCC_ENABLE_SSL)
set(AT_LIBS ${AT_LIBS} ${OPENSSL_LIBRARIES}) set(AT_LIBS ${AT_LIBS} ${OPENSSL_LIBRARIES} crypt32)
endif() endif()
if(WIN32) if(WEBCC_ENABLE_GZIP)
# TODO: crypt32 should be ssl related. if(WIN32)
set(AT_LIBS ${AT_LIBS} zlibstatic crypt32) set(AT_LIBS ${AT_LIBS} zlibstatic)
else() else()
set(AT_LIBS ${AT_LIBS} ${ZLIB_LIBRARIES}) set(AT_LIBS ${AT_LIBS} ${ZLIB_LIBRARIES})
endif()
endif() endif()
if(UNIX) if(UNIX)

@ -48,8 +48,13 @@ static void AssertGet(webcc::ResponsePtr r) {
Json::Value headers = json["headers"]; Json::Value headers = json["headers"];
EXPECT_EQ("application/json", headers["Accept"].asString()); EXPECT_EQ("application/json", headers["Accept"].asString());
EXPECT_EQ("gzip, deflate", headers["Accept-Encoding"].asString());
EXPECT_EQ("httpbin.org", headers["Host"].asString()); EXPECT_EQ("httpbin.org", headers["Host"].asString());
#if WEBCC_ENABLE_GZIP
EXPECT_EQ("gzip, deflate", headers["Accept-Encoding"].asString());
#else
EXPECT_EQ("identity", headers["Accept-Encoding"].asString());
#endif // WEBCC_ENABLE_GZIP
} }
TEST(ClientTest, Get_RequestFunc) { TEST(ClientTest, Get_RequestFunc) {
@ -110,6 +115,8 @@ TEST(ClientTest, Get_SSL) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if WEBCC_ENABLE_GZIP
// Test Gzip compressed response. // Test Gzip compressed response.
TEST(ClientTest, Compression_Gzip) { TEST(ClientTest, Compression_Gzip) {
webcc::ClientSession session; webcc::ClientSession session;
@ -142,6 +149,8 @@ TEST(ClientTest, Compression_Deflate) {
} }
} }
#endif // WEBCC_ENABLE_GZIP
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Test persistent (keep-alive) connections. // Test persistent (keep-alive) connections.

@ -4,13 +4,15 @@
set(EXAMPLE_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}") set(EXAMPLE_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}")
if(WEBCC_ENABLE_SSL) if(WEBCC_ENABLE_SSL)
set(EXAMPLE_LIBS ${EXAMPLE_LIBS} ${OPENSSL_LIBRARIES}) set(EXAMPLE_LIBS ${EXAMPLE_LIBS} ${OPENSSL_LIBRARIES} crypt32)
endif() endif()
if(WIN32) if(WEBCC_ENABLE_GZIP)
set(EXAMPLE_LIBS ${EXAMPLE_LIBS} zlibstatic crypt32) if(WIN32)
else() set(EXAMPLE_LIBS ${EXAMPLE_LIBS} zlibstatic)
set(EXAMPLE_LIBS ${EXAMPLE_LIBS} ${ZLIB_LIBRARIES}) else()
set(EXAMPLE_LIBS ${EXAMPLE_LIBS} ${ZLIB_LIBRARIES})
endif()
endif() endif()
if(UNIX) if(UNIX)

@ -10,24 +10,26 @@ set(UT_SRCS
set(UT_TARGET_NAME webcc_unittest) set(UT_TARGET_NAME webcc_unittest)
# Common libraries to link. # Common libraries to link.
set(TEST_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}") set(UT_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}")
if(WEBCC_ENABLE_SSL) if(WEBCC_ENABLE_SSL)
set(TEST_LIBS ${TEST_LIBS} ${OPENSSL_LIBRARIES}) set(UT_LIBS ${UT_LIBS} ${OPENSSL_LIBRARIES} crypt32)
endif() endif()
if(WIN32) if(WEBCC_ENABLE_GZIP)
set(TEST_LIBS ${TEST_LIBS} zlibstatic crypt32) if(WIN32)
else() set(UT_LIBS ${UT_LIBS} zlibstatic)
set(TEST_LIBS ${TEST_LIBS} ${ZLIB_LIBRARIES}) else()
set(UT_LIBS ${UT_LIBS} ${ZLIB_LIBRARIES})
endif()
endif() endif()
if(UNIX) if(UNIX)
# Add `-ldl` for Linux to avoid "undefined reference to `dlopen'". # Add `-ldl` for Linux to avoid "undefined reference to `dlopen'".
set(TEST_LIBS ${TEST_LIBS} ${CMAKE_DL_LIBS}) set(UT_LIBS ${UT_LIBS} ${CMAKE_DL_LIBS})
endif() endif()
add_executable(${UT_TARGET_NAME} ${UT_SRCS}) add_executable(${UT_TARGET_NAME} ${UT_SRCS})
target_link_libraries(${UT_TARGET_NAME} webcc gtest ${TEST_LIBS}) target_link_libraries(${UT_TARGET_NAME} webcc gtest ${UT_LIBS})
add_test(${UT_TARGET_NAME} ${UT_TARGET_NAME}) add_test(${UT_TARGET_NAME} ${UT_TARGET_NAME})

@ -8,7 +8,7 @@
#include <iostream> #include <iostream>
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if 0
// HTTP GET request parser test fixture. // HTTP GET request parser test fixture.
class GetRequestParserTest : public testing::Test { class GetRequestParserTest : public testing::Test {
protected: protected:
@ -145,7 +145,6 @@ TEST_F(PostRequestParserTest, ParseByteWise) {
CheckResult(); CheckResult();
} }
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

@ -18,6 +18,10 @@ file(GLOB SRCS
${CMAKE_CURRENT_SOURCE_DIR}/*.cc ${CMAKE_CURRENT_SOURCE_DIR}/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/*.h) ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
if(NOT WEBCC_ENABLE_GZIP)
list(REMOVE_ITEM SRCS "gzip.h" "gzip.cc")
endif()
set(TARGET webcc) set(TARGET webcc)
add_library(${TARGET} STATIC ${SRCS}) add_library(${TARGET} STATIC ${SRCS})

@ -158,6 +158,7 @@ void ClientSession::InitHeaders() {
// Content-Encoding Tokens: // Content-Encoding Tokens:
// (https://en.wikipedia.org/wiki/HTTP_compression) // (https://en.wikipedia.org/wiki/HTTP_compression)
//
// * compress ¨C UNIX "compress" program method (historic; deprecated in most // * compress ¨C UNIX "compress" program method (historic; deprecated in most
// applications and replaced by gzip or deflate); // applications and replaced by gzip or deflate);
// * deflate ¨C compression based on the deflate algorithm, a combination of // * deflate ¨C compression based on the deflate algorithm, a combination of
@ -177,7 +178,11 @@ void ClientSession::InitHeaders() {
// the raw deflate compressed data format. // the raw deflate compressed data format.
// Simply put, "deflate" is not recommended for HTTP 1.1 encoding. // Simply put, "deflate" is not recommended for HTTP 1.1 encoding.
#if WEBCC_ENABLE_GZIP
headers_.Set(kAcceptEncoding, "gzip, deflate"); headers_.Set(kAcceptEncoding, "gzip, deflate");
#else
headers_.Set(kAcceptEncoding, "identity");
#endif // WEBCC_ENABLE_GZIP
headers_.Set(kAccept, "*/*"); headers_.Set(kAccept, "*/*");

@ -12,6 +12,9 @@
#endif #endif
// Set 1/0 to enable/disable SSL/HTTPS. // Set 1/0 to enable/disable SSL/HTTPS.
#define WEBCC_ENABLE_SSL 1 #define WEBCC_ENABLE_SSL 0
// Set 1/0 to enable/disable GZIP compression.
#define WEBCC_ENABLE_GZIP 0
#endif // WEBCC_CONFIG_H_ #endif // WEBCC_CONFIG_H_

@ -16,4 +16,7 @@
// Set 1/0 to enable/disable SSL/HTTPS. // Set 1/0 to enable/disable SSL/HTTPS.
#define WEBCC_ENABLE_SSL @WEBCC_ENABLE_SSL@ #define WEBCC_ENABLE_SSL @WEBCC_ENABLE_SSL@
// Set 1/0 to enable/disable GZIP compression.
#define WEBCC_ENABLE_GZIP @WEBCC_ENABLE_GZIP@
#endif // WEBCC_CONFIG_H_ #endif // WEBCC_CONFIG_H_

@ -5,6 +5,8 @@
#include <exception> #include <exception>
#include <string> #include <string>
#include "webcc/config.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Macros // Macros

@ -1,4 +1,4 @@
#include "webcc/zlib_wrapper.h" #include "webcc/gzip.h"
#include <cassert> #include <cassert>
#include <utility> // std::move #include <utility> // std::move
@ -8,6 +8,7 @@
#include "webcc/logger.h" #include "webcc/logger.h"
namespace webcc { namespace webcc {
namespace gzip {
bool Compress(const std::string& input, std::string* output) { bool Compress(const std::string& input, std::string* output) {
output->clear(); output->clear();
@ -125,4 +126,5 @@ bool Decompress(const std::string& input, std::string* output) {
return true; return true;
} }
} // namespace gzip
} // namespace webcc } // namespace webcc

@ -1,9 +1,10 @@
#ifndef WEBCC_ZLIB_WRAPPER_H_ #ifndef WEBCC_GZIP_H_
#define WEBCC_ZLIB_WRAPPER_H_ #define WEBCC_GZIP_H_
#include <string> #include <string>
namespace webcc { namespace webcc {
namespace gzip {
// Compress the input string to gzip format output. // Compress the input string to gzip format output.
bool Compress(const std::string& input, std::string* output); bool Compress(const std::string& input, std::string* output);
@ -12,6 +13,7 @@ bool Compress(const std::string& input, std::string* output);
// formats. // formats.
bool Decompress(const std::string& input, std::string* output); bool Decompress(const std::string& input, std::string* output);
} // namespace gzip
} // namespace webcc } // namespace webcc
#endif // WEBCC_ZLIB_WRAPPER_H_ #endif // WEBCC_GZIP_H_

@ -5,7 +5,10 @@
#include "webcc/logger.h" #include "webcc/logger.h"
#include "webcc/message.h" #include "webcc/message.h"
#include "webcc/utility.h" #include "webcc/utility.h"
#include "webcc/zlib_wrapper.h"
#if WEBCC_ENABLE_GZIP
#include "webcc/gzip.h"
#endif
namespace webcc { namespace webcc {
@ -323,16 +326,29 @@ bool Parser::Finish() {
return true; return true;
} }
#if WEBCC_ENABLE_GZIP
LOG_INFO("Decompress the HTTP content..."); LOG_INFO("Decompress the HTTP content...");
std::string decompressed; std::string decompressed;
if (!Decompress(content_, &decompressed)) { if (!gzip::Decompress(content_, &decompressed)) {
LOG_ERRO("Cannot decompress the HTTP content!"); LOG_ERRO("Cannot decompress the HTTP content!");
return false; return false;
} }
message_->SetContent(std::move(decompressed), false); message_->SetContent(std::move(decompressed), false);
return true; return true;
#else
LOG_WARN("Compressed HTTP content remains untouched.");
message_->SetContent(std::move(content_), false);
return true;
#endif // WEBCC_ENABLE_GZIP
} }
void Parser::AppendContent(const char* data, std::size_t count) { void Parser::AppendContent(const char* data, std::size_t count) {

@ -2,7 +2,6 @@
#include "webcc/logger.h" #include "webcc/logger.h"
#include "webcc/utility.h" #include "webcc/utility.h"
#include <iostream>
namespace webcc { namespace webcc {
@ -74,10 +73,6 @@ void Request::Prepare() {
// Append payload of content data. // Append payload of content data.
payload_.insert(payload_.end(), data_payload.begin(), data_payload.end()); payload_.insert(payload_.end(), data_payload.begin(), data_payload.end());
std::string str;
CopyPayload(&str);
std::cout << str;
} }
void Request::CreateStartLine() { void Request::CreateStartLine() {

@ -78,7 +78,6 @@ private:
Url url_; Url url_;
// Files to upload for a POST request.
std::vector<FormPartPtr> form_parts_; std::vector<FormPartPtr> form_parts_;
std::string boundary_; std::string boundary_;

@ -3,7 +3,10 @@
#include "webcc/base64.h" #include "webcc/base64.h"
#include "webcc/logger.h" #include "webcc/logger.h"
#include "webcc/utility.h" #include "webcc/utility.h"
#include "webcc/zlib_wrapper.h"
#if WEBCC_ENABLE_GZIP
#include "webcc/gzip.h"
#endif
namespace webcc { namespace webcc {
@ -76,9 +79,10 @@ RequestBuilder& RequestBuilder::AuthToken(const std::string& token) {
} }
void RequestBuilder::SetContent(RequestPtr request, std::string&& data) { void RequestBuilder::SetContent(RequestPtr request, std::string&& data) {
#if WEBCC_ENABLE_GZIP
if (gzip_ && data.size() > kGzipThreshold) { if (gzip_ && data.size() > kGzipThreshold) {
std::string compressed; std::string compressed;
if (Compress(data, &compressed)) { if (gzip::Compress(data, &compressed)) {
request->SetContent(std::move(compressed), true); request->SetContent(std::move(compressed), true);
request->SetHeader(headers::kContentEncoding, "gzip"); request->SetHeader(headers::kContentEncoding, "gzip");
return; return;
@ -86,6 +90,7 @@ void RequestBuilder::SetContent(RequestPtr request, std::string&& data) {
LOG_WARN("Cannot compress the content data!"); LOG_WARN("Cannot compress the content data!");
} }
#endif // WEBCC_ENABLE_GZIP
request->SetContent(std::move(data), true); request->SetContent(std::move(data), true);
} }

@ -5,7 +5,10 @@
#include "webcc/logger.h" #include "webcc/logger.h"
#include "webcc/url.h" #include "webcc/url.h"
#include "webcc/zlib_wrapper.h"
#if WEBCC_ENABLE_GZIP
#include "webcc/gzip.h"
#endif
namespace webcc { namespace webcc {
@ -15,12 +18,11 @@ bool RestRequestHandler::Bind(RestServicePtr service, const std::string& url,
} }
void RestRequestHandler::HandleConnection(ConnectionPtr connection) { void RestRequestHandler::HandleConnection(ConnectionPtr connection) {
RequestPtr http_request = connection->request(); RequestPtr request = connection->request();
assert(http_request);
const Url& url = http_request->url(); const Url& url = request->url();
RestRequest rest_request{ http_request }; RestRequest rest_request{ request };
// Get service by URL path. // Get service by URL path.
std::string path = "/" + url.path(); std::string path = "/" + url.path();
@ -35,29 +37,34 @@ void RestRequestHandler::HandleConnection(ConnectionPtr connection) {
RestResponse rest_response; RestResponse rest_response;
service->Handle(rest_request, &rest_response); service->Handle(rest_request, &rest_response);
auto http_response = std::make_shared<Response>(rest_response.status); auto response = std::make_shared<Response>(rest_response.status);
if (!rest_response.content.empty()) { if (!rest_response.content.empty()) {
if (!rest_response.media_type.empty()) { if (!rest_response.media_type.empty()) {
http_response->SetContentType(rest_response.media_type, response->SetContentType(rest_response.media_type, rest_response.charset);
rest_response.charset);
} }
SetContent(request, response, std::move(rest_response.content));
}
// Send response back to client.
connection->SendResponse(response);
}
// Only support gzip for response compression. void RestRequestHandler::SetContent(RequestPtr request, ResponsePtr response,
if (rest_response.content.size() > kGzipThreshold && std::string&& content) {
http_request->AcceptEncodingGzip()) { #if WEBCC_ENABLE_GZIP
std::string compressed; // Only support gzip (no deflate) for response compression.
if (Compress(rest_response.content, &compressed)) { if (content.size() > kGzipThreshold && request->AcceptEncodingGzip()) {
http_response->SetHeader(headers::kContentEncoding, "gzip"); std::string compressed;
http_response->SetContent(std::move(compressed), true); if (gzip::Compress(content, &compressed)) {
} response->SetHeader(headers::kContentEncoding, "gzip");
} else { response->SetContent(std::move(compressed), true);
http_response->SetContent(std::move(rest_response.content), true); return;
} }
} }
#endif // WEBCC_ENABLE_GZIP
// Send response back to client. response->SetContent(std::move(content), true);
connection->SendResponse(http_response);
} }
} // namespace webcc } // namespace webcc

@ -21,6 +21,9 @@ public:
private: private:
void HandleConnection(ConnectionPtr connection) final; void HandleConnection(ConnectionPtr connection) final;
void SetContent(RequestPtr request, ResponsePtr response,
std::string&& content);
private: private:
RestServiceManager service_manager_; RestServiceManager service_manager_;
}; };

@ -1,16 +1,10 @@
#ifndef WEBCC_UTILITY_H_ #ifndef WEBCC_UTILITY_H_
#define WEBCC_UTILITY_H_ #define WEBCC_UTILITY_H_
#include <iosfwd>
#include <string> #include <string>
namespace webcc { namespace webcc {
// Get the timestamp for HTTP Date header field.
// E.g., Wed, 21 Oct 2015 07:28:00 GMT
// See: https://tools.ietf.org/html/rfc7231#section-7.1.1.2
std::string GetHttpDateTimestamp();
std::string RandomUuid(); std::string RandomUuid();
} // namespace webcc } // namespace webcc

Loading…
Cancel
Save