From 437e81a3018ac484fd9dc8911a7a93d1b1492cb2 Mon Sep 17 00:00:00 2001 From: krunal1313 Date: Mon, 3 Jul 2023 13:05:52 +0530 Subject: [PATCH] handling small file without chunks --- include/http_server.h | 2 + src/http_server.cpp | 103 ++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/include/http_server.h b/include/http_server.h index 1ced92e7..ae017abf 100644 --- a/include/http_server.h +++ b/include/http_server.h @@ -244,6 +244,8 @@ private: static bool is_write_request(const std::string& root_resource, const std::string& http_method); + static void handle_gzip(const std::shared_ptr& request); + public: HttpServer(const std::string & version, const std::string & listen_address, uint32_t listen_port, diff --git a/src/http_server.cpp b/src/http_server.cpp index 2aa4a415..a0a73b27 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -525,6 +525,12 @@ int HttpServer::catch_all_handler(h2o_handler_t *_h2o_handler, h2o_req_t *req) { if(req->proceed_req == nullptr) { // Full request body is already available, so we don't care if handler is async or not //LOG(INFO) << "Full request body is already available: " << req->entity.len; + //process gzip file by checking header + if((request->body.size() > 2) && + (31 == (int)request->body[0] && -117 == (int)request->body[1])) { + handle_gzip(request); + } + request->last_chunk_aggregate = true; return process_request(request, response, rpath, h2o_handler, use_meta_thread_pool); } else { @@ -631,51 +637,6 @@ int HttpServer::async_req_cb(void *ctx, int is_end_stream) { if(can_process_async || is_end_stream) { // For async streaming requests, handler should be invoked for every aggregated chunk // For a non streaming request, buffer body and invoke only at the end - if(!request->zstream_initialized && (request->body.size() > 2) && - (31 == (int)request->body[0] && -117 == (int)request->body[1])) { //gzip header - request->zs.zalloc = Z_NULL; - request->zs.zfree = Z_NULL; - request->zs.opaque = Z_NULL; - request->zs.avail_in = 0; - request->zs.next_in = Z_NULL; - - if (inflateInit2(&request->zs, 16 + MAX_WBITS) != Z_OK) - throw (std::runtime_error("inflateInit failed while decompressing.")); - request->zstream_initialized = true; - } - - if(request->zstream_initialized) { - std::string outbuffer; - outbuffer.resize(10 * request->body.size()); - - request->zs.next_in = (Bytef *) request->body.c_str(); - request->zs.avail_in = request->body.size(); - std::size_t size_uncompressed = 0; - int ret = 0; - do { - request->zs.avail_out = static_cast(outbuffer.size()); - request->zs.next_out = reinterpret_cast(&outbuffer[0] + size_uncompressed); - ret = inflate(&request->zs, Z_FINISH); - if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) { - std::string error_msg = request->zs.msg; - inflateEnd(&request->zs); - throw std::runtime_error(error_msg); - } - - size_uncompressed += (outbuffer.size() - request->zs.avail_out); - } while (request->zs.avail_out == 0); - - if (ret == Z_STREAM_END) { - request->zstream_initialized = false; - inflateEnd(&request->zs); - } - - outbuffer.resize(size_uncompressed); - - request->body = outbuffer; - request->chunk_len = outbuffer.size(); - } - if(request->first_chunk_aggregate) { request->first_chunk_aggregate = false; } @@ -690,11 +651,63 @@ int HttpServer::async_req_cb(void *ctx, int is_end_stream) { return 0; } +void HttpServer::handle_gzip(const std::shared_ptr& request) { + if(!request->zstream_initialized) { + request->zs.zalloc = Z_NULL; + request->zs.zfree = Z_NULL; + request->zs.opaque = Z_NULL; + request->zs.avail_in = 0; + request->zs.next_in = Z_NULL; + + if (inflateInit2(&request->zs, 16 + MAX_WBITS) != Z_OK) + throw (std::runtime_error("inflateInit failed while decompressing.")); + request->zstream_initialized = true; + } + + if(request->zstream_initialized) { + std::string outbuffer; + outbuffer.resize(10 * request->body.size()); + + request->zs.next_in = (Bytef *) request->body.c_str(); + request->zs.avail_in = request->body.size(); + std::size_t size_uncompressed = 0; + int ret = 0; + do { + request->zs.avail_out = static_cast(outbuffer.size()); + request->zs.next_out = reinterpret_cast(&outbuffer[0] + size_uncompressed); + ret = inflate(&request->zs, Z_FINISH); + if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) { + std::string error_msg = request->zs.msg; + inflateEnd(&request->zs); + throw std::runtime_error(error_msg); + } + + size_uncompressed += (outbuffer.size() - request->zs.avail_out); + } while (request->zs.avail_out == 0); + + if (ret == Z_STREAM_END) { + request->zstream_initialized = false; + inflateEnd(&request->zs); + } + + outbuffer.resize(size_uncompressed); + + request->body = outbuffer; + request->chunk_len = outbuffer.size(); + } +} + int HttpServer::process_request(const std::shared_ptr& request, const std::shared_ptr& response, route_path *rpath, const h2o_custom_req_handler_t *handler, const bool use_meta_thread_pool) { //LOG(INFO) << "process_request called"; + //check if it's first gzip chunk or is gzip stream initialized + if(((request->body.size() > 2) && + (31 == (int)request->body[0] && -117 == (int)request->body[1])) || request->zstream_initialized) { + handle_gzip(request); + } + const std::string& root_resource = (rpath->path_parts.empty()) ? "" : rpath->path_parts[0]; if(root_resource == "multi_search") {