diff --git a/dbms/CMakeLists.txt b/dbms/CMakeLists.txt index ec69a4389a7..a86de61827b 100644 --- a/dbms/CMakeLists.txt +++ b/dbms/CMakeLists.txt @@ -89,6 +89,9 @@ set(dbms_sources) include(../cmake/dbms_glob_sources.cmake) +# temp ugly hack +include_directories(${BROTLI_INCLUDE_DIR}) + add_headers_and_sources(clickhouse_common_io src/Common) add_headers_and_sources(clickhouse_common_io src/Common/HashTable) add_headers_and_sources(clickhouse_common_io src/IO) diff --git a/dbms/programs/server/HTTPHandler.cpp b/dbms/programs/server/HTTPHandler.cpp index f75f801cf27..2d531b3840f 100644 --- a/dbms/programs/server/HTTPHandler.cpp +++ b/dbms/programs/server/HTTPHandler.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -396,19 +397,25 @@ void HTTPHandler::processQuery( String http_request_compression_method_str = request.get("Content-Encoding", ""); if (!http_request_compression_method_str.empty()) { - ZlibCompressionMethod method; - if (http_request_compression_method_str == "gzip") - { - method = ZlibCompressionMethod::Gzip; - } - else if (http_request_compression_method_str == "deflate") - { - method = ZlibCompressionMethod::Zlib; - } - else + do { + if (http_request_compression_method_str == "gzip") + { + in_post = std::make_unique(*in_post_raw, ZlibCompressionMethod::Gzip); + break; + } + if (http_request_compression_method_str == "deflate") + { + in_post = std::make_unique(*in_post_raw, ZlibCompressionMethod::Zlib); + break; + } + if (http_request_compression_method_str == "br") + { + in_post = std::make_unique(*in_post_raw); + break; + } throw Exception("Unknown Content-Encoding of HTTP request: " + http_request_compression_method_str, - ErrorCodes::UNKNOWN_COMPRESSION_METHOD); - in_post = std::make_unique(*in_post_raw, method); + ErrorCodes::UNKNOWN_COMPRESSION_METHOD); + } while(0); } else in_post = std::move(in_post_raw); diff --git a/dbms/src/IO/BrotliReadBuffer.cpp b/dbms/src/IO/BrotliReadBuffer.cpp new file mode 100644 index 00000000000..f67e9ffc78d --- /dev/null +++ b/dbms/src/IO/BrotliReadBuffer.cpp @@ -0,0 +1,41 @@ +#include "BrotliReadBuffer.h" + +namespace DB +{ +BrotliReadBuffer::BrotliReadBuffer(ReadBuffer &in_, size_t buf_size, char *existing_memory, size_t alignment) + : BufferWithOwnMemory(buf_size, existing_memory, alignment) + , in(in_) + , eof(false) +{ + bstate_ = BrotliDecoderCreateInstance(NULL,NULL,NULL); +} + +BrotliReadBuffer::~BrotliReadBuffer() +{ + BrotliDecoderDestroyInstance(bstate_); +} + +bool BrotliReadBuffer::nextImpl() +{ + if (eof) + return false; + + auto ptr_in = reinterpret_cast(in.position()); + size_t size_in = in.buffer().end() - in.position(); + + auto ptr_out = reinterpret_cast(internal_buffer.begin()); + size_t size_out = internal_buffer.size(); + + BrotliDecoderDecompressStream(bstate_, &size_in, &ptr_in, &size_out, &ptr_out, nullptr); + + in.position() = in.buffer().end() - size_in; + working_buffer.resize(internal_buffer.size() - size_out); + + if (in.eof()) { + eof = true; + return working_buffer.size() != 0; + } + + return true; +} +} \ No newline at end of file diff --git a/dbms/src/IO/BrotliReadBuffer.h b/dbms/src/IO/BrotliReadBuffer.h new file mode 100644 index 00000000000..cc06587add4 --- /dev/null +++ b/dbms/src/IO/BrotliReadBuffer.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include + +namespace DB { + +class BrotliReadBuffer : public BufferWithOwnMemory { +public: + BrotliReadBuffer( + ReadBuffer &in_, + size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE, + char *existing_memory = nullptr, + size_t alignment = 0); + + ~BrotliReadBuffer() override; + +private: + bool nextImpl() override; + + ReadBuffer ∈ + BrotliDecoderState * bstate_; + bool eof; +}; +} \ No newline at end of file