You've already forked cpp-httplib
							
							Fix #557
This commit is contained in:
		
							
								
								
									
										118
									
								
								httplib.h
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								httplib.h
									
									
									
									
									
								
							@@ -401,11 +401,11 @@ struct Response {
 | 
				
			|||||||
  void set_content(std::string s, const char *content_type);
 | 
					  void set_content(std::string s, const char *content_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_content_provider(
 | 
					  void set_content_provider(
 | 
				
			||||||
      size_t length, ContentProvider provider,
 | 
					      size_t length, const char *content_type, ContentProvider provider,
 | 
				
			||||||
      std::function<void()> resource_releaser = [] {});
 | 
					      std::function<void()> resource_releaser = [] {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_chunked_content_provider(
 | 
					  void set_chunked_content_provider(
 | 
				
			||||||
      ChunkedContentProvider provider,
 | 
					      const char *content_type, ChunkedContentProvider provider,
 | 
				
			||||||
      std::function<void()> resource_releaser = [] {});
 | 
					      std::function<void()> resource_releaser = [] {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Response() = default;
 | 
					  Response() = default;
 | 
				
			||||||
@@ -2263,8 +2263,7 @@ inline const char *status_message(int status) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
					inline bool can_compress_content_type(const std::string &content_type) {
 | 
				
			||||||
inline bool can_compress(const std::string &content_type) {
 | 
					 | 
				
			||||||
  return !content_type.find("text/") || content_type == "image/svg+xml" ||
 | 
					  return !content_type.find("text/") || content_type == "image/svg+xml" ||
 | 
				
			||||||
         content_type == "application/javascript" ||
 | 
					         content_type == "application/javascript" ||
 | 
				
			||||||
         content_type == "application/json" ||
 | 
					         content_type == "application/json" ||
 | 
				
			||||||
@@ -2272,6 +2271,18 @@ inline bool can_compress(const std::string &content_type) {
 | 
				
			|||||||
         content_type == "application/xhtml+xml";
 | 
					         content_type == "application/xhtml+xml";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool can_compress_content(const Request &req, const Response &res) {
 | 
				
			||||||
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
 | 
					  const auto &encodings = req.get_header_value("Accept-Encoding");
 | 
				
			||||||
 | 
					  return encodings.find("gzip") != std::string::npos &&
 | 
				
			||||||
 | 
					         detail::can_compress_content_type(
 | 
				
			||||||
 | 
					             res.get_header_value("Content-Type"));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
class compressor {
 | 
					class compressor {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  compressor() {
 | 
					  compressor() {
 | 
				
			||||||
@@ -2310,7 +2321,7 @@ public:
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    } while (strm_.avail_out == 0);
 | 
					    } while (strm_.avail_out == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(ret == Z_STREAM_END);
 | 
					    assert((last && ret == Z_STREAM_END) || (!last && ret == Z_OK));
 | 
				
			||||||
    assert(strm_.avail_in == 0);
 | 
					    assert(strm_.avail_in == 0);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2660,39 +2671,90 @@ inline ssize_t write_content(Stream &strm, ContentProvider content_provider,
 | 
				
			|||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
inline ssize_t write_content_chunked(Stream &strm,
 | 
					inline ssize_t write_content_chunked(Stream &strm,
 | 
				
			||||||
                                     ContentProvider content_provider,
 | 
					                                     ContentProvider content_provider,
 | 
				
			||||||
                                     T is_shutting_down) {
 | 
					                                     T is_shutting_down, bool compress) {
 | 
				
			||||||
  size_t offset = 0;
 | 
					  size_t offset = 0;
 | 
				
			||||||
  auto data_available = true;
 | 
					  auto data_available = true;
 | 
				
			||||||
  ssize_t total_written_length = 0;
 | 
					  ssize_t total_written_length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto ok = true;
 | 
					  auto ok = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  DataSink data_sink;
 | 
					  DataSink data_sink;
 | 
				
			||||||
  data_sink.write = [&](const char *d, size_t l) {
 | 
					 | 
				
			||||||
    if (ok) {
 | 
					 | 
				
			||||||
      data_available = l > 0;
 | 
					 | 
				
			||||||
      offset += l;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
 | 
					  detail::compressor compressor;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  data_sink.write = [&](const char *d, size_t l) {
 | 
				
			||||||
 | 
					    if (!ok) { return; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data_available = l > 0;
 | 
				
			||||||
 | 
					    offset += l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string payload;
 | 
				
			||||||
 | 
					    if (compress) {
 | 
				
			||||||
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
 | 
					      if (!compressor.compress(d, l, false,
 | 
				
			||||||
 | 
					                               [&](const char *data, size_t data_len) {
 | 
				
			||||||
 | 
					                                 payload.append(data, data_len);
 | 
				
			||||||
 | 
					                                 return true;
 | 
				
			||||||
 | 
					                               })) {
 | 
				
			||||||
 | 
					        ok = false;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      payload = std::string(d, l);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!payload.empty()) {
 | 
				
			||||||
      // Emit chunked response header and footer for each chunk
 | 
					      // Emit chunked response header and footer for each chunk
 | 
				
			||||||
      auto chunk = from_i_to_hex(l) + "\r\n" + std::string(d, l) + "\r\n";
 | 
					      auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n";
 | 
				
			||||||
      if (write_data(strm, chunk.data(), chunk.size())) {
 | 
					      if (write_data(strm, chunk.data(), chunk.size())) {
 | 
				
			||||||
        total_written_length += chunk.size();
 | 
					        total_written_length += chunk.size();
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        ok = false;
 | 
					        ok = false;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  data_sink.done = [&](void) {
 | 
					  data_sink.done = [&](void) {
 | 
				
			||||||
 | 
					    if (!ok) { return; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data_available = false;
 | 
					    data_available = false;
 | 
				
			||||||
    if (ok) {
 | 
					
 | 
				
			||||||
      static const std::string done_marker("0\r\n\r\n");
 | 
					    if (compress) {
 | 
				
			||||||
      if (write_data(strm, done_marker.data(), done_marker.size())) {
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
        total_written_length += done_marker.size();
 | 
					      std::string payload;
 | 
				
			||||||
      } else {
 | 
					      if (!compressor.compress(nullptr, 0, true,
 | 
				
			||||||
 | 
					                               [&](const char *data, size_t data_len) {
 | 
				
			||||||
 | 
					                                 payload.append(data, data_len);
 | 
				
			||||||
 | 
					                                 return true;
 | 
				
			||||||
 | 
					                               })) {
 | 
				
			||||||
        ok = false;
 | 
					        ok = false;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!payload.empty()) {
 | 
				
			||||||
 | 
					        // Emit chunked response header and footer for each chunk
 | 
				
			||||||
 | 
					        auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n";
 | 
				
			||||||
 | 
					        if (write_data(strm, chunk.data(), chunk.size())) {
 | 
				
			||||||
 | 
					          total_written_length += chunk.size();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          ok = false;
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static const std::string done_marker("0\r\n\r\n");
 | 
				
			||||||
 | 
					    if (write_data(strm, done_marker.data(), done_marker.size())) {
 | 
				
			||||||
 | 
					      total_written_length += done_marker.size();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      ok = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  data_sink.is_writable = [&](void) { return ok && strm.is_writable(); };
 | 
					  data_sink.is_writable = [&](void) { return ok && strm.is_writable(); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (data_available && !is_shutting_down()) {
 | 
					  while (data_available && !is_shutting_down()) {
 | 
				
			||||||
@@ -3515,9 +3577,11 @@ inline void Response::set_content(std::string s, const char *content_type) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void
 | 
					inline void
 | 
				
			||||||
Response::set_content_provider(size_t in_length, ContentProvider provider,
 | 
					Response::set_content_provider(size_t in_length, const char *content_type,
 | 
				
			||||||
 | 
					                               ContentProvider provider,
 | 
				
			||||||
                               std::function<void()> resource_releaser) {
 | 
					                               std::function<void()> resource_releaser) {
 | 
				
			||||||
  assert(in_length > 0);
 | 
					  assert(in_length > 0);
 | 
				
			||||||
 | 
					  set_header("Content-Type", content_type);
 | 
				
			||||||
  content_length_ = in_length;
 | 
					  content_length_ = in_length;
 | 
				
			||||||
  content_provider_ = [provider](size_t offset, size_t length, DataSink &sink) {
 | 
					  content_provider_ = [provider](size_t offset, size_t length, DataSink &sink) {
 | 
				
			||||||
    return provider(offset, length, sink);
 | 
					    return provider(offset, length, sink);
 | 
				
			||||||
@@ -3526,7 +3590,9 @@ Response::set_content_provider(size_t in_length, ContentProvider provider,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void Response::set_chunked_content_provider(
 | 
					inline void Response::set_chunked_content_provider(
 | 
				
			||||||
    ChunkedContentProvider provider, std::function<void()> resource_releaser) {
 | 
					    const char *content_type, ChunkedContentProvider provider,
 | 
				
			||||||
 | 
					    std::function<void()> resource_releaser) {
 | 
				
			||||||
 | 
					  set_header("Content-Type", content_type);
 | 
				
			||||||
  content_length_ = 0;
 | 
					  content_length_ = 0;
 | 
				
			||||||
  content_provider_ = [provider](size_t offset, size_t, DataSink &sink) {
 | 
					  content_provider_ = [provider](size_t offset, size_t, DataSink &sink) {
 | 
				
			||||||
    return provider(offset, sink);
 | 
					    return provider(offset, sink);
 | 
				
			||||||
@@ -3894,6 +3960,8 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
 | 
				
			|||||||
                        "multipart/byteranges; boundary=" + boundary);
 | 
					                        "multipart/byteranges; boundary=" + boundary);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool compress = detail::can_compress_content(req, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (res.body.empty()) {
 | 
					  if (res.body.empty()) {
 | 
				
			||||||
    if (res.content_length_ > 0) {
 | 
					    if (res.content_length_ > 0) {
 | 
				
			||||||
      size_t length = 0;
 | 
					      size_t length = 0;
 | 
				
			||||||
@@ -3915,6 +3983,7 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      if (res.content_provider_) {
 | 
					      if (res.content_provider_) {
 | 
				
			||||||
        res.set_header("Transfer-Encoding", "chunked");
 | 
					        res.set_header("Transfer-Encoding", "chunked");
 | 
				
			||||||
 | 
					        if (compress) { res.set_header("Content-Encoding", "gzip"); }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        res.set_header("Content-Length", "0");
 | 
					        res.set_header("Content-Length", "0");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -3936,11 +4005,9 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
 | 
				
			|||||||
          detail::make_multipart_ranges_data(req, res, boundary, content_type);
 | 
					          detail::make_multipart_ranges_data(req, res, boundary, content_type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
					 | 
				
			||||||
    // TODO: 'Accept-Encoding' has gzip, not gzip;q=0
 | 
					    // TODO: 'Accept-Encoding' has gzip, not gzip;q=0
 | 
				
			||||||
    const auto &encodings = req.get_header_value("Accept-Encoding");
 | 
					    if (compress) {
 | 
				
			||||||
    if (encodings.find("gzip") != std::string::npos &&
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
        detail::can_compress(res.get_header_value("Content-Type"))) {
 | 
					 | 
				
			||||||
      std::string compressed;
 | 
					      std::string compressed;
 | 
				
			||||||
      detail::compressor compressor;
 | 
					      detail::compressor compressor;
 | 
				
			||||||
      if (!compressor.compress(res.body.data(), res.body.size(), true,
 | 
					      if (!compressor.compress(res.body.data(), res.body.size(), true,
 | 
				
			||||||
@@ -3952,8 +4019,8 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      res.body.swap(compressed);
 | 
					      res.body.swap(compressed);
 | 
				
			||||||
      res.set_header("Content-Encoding", "gzip");
 | 
					      res.set_header("Content-Encoding", "gzip");
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto length = std::to_string(res.body.size());
 | 
					    auto length = std::to_string(res.body.size());
 | 
				
			||||||
    res.set_header("Content-Length", length);
 | 
					    res.set_header("Content-Length", length);
 | 
				
			||||||
@@ -4014,8 +4081,9 @@ Server::write_content_with_provider(Stream &strm, const Request &req,
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
 | 
					    auto compress = detail::can_compress_content(req, res);
 | 
				
			||||||
    if (detail::write_content_chunked(strm, res.content_provider_,
 | 
					    if (detail::write_content_chunked(strm, res.content_provider_,
 | 
				
			||||||
                                      is_shutting_down) < 0) {
 | 
					                                      is_shutting_down, compress) < 0) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										35
									
								
								test/test.cc
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								test/test.cc
									
									
									
									
									
								
							@@ -885,7 +885,7 @@ protected:
 | 
				
			|||||||
        .Get("/streamed-chunked",
 | 
					        .Get("/streamed-chunked",
 | 
				
			||||||
             [&](const Request & /*req*/, Response &res) {
 | 
					             [&](const Request & /*req*/, Response &res) {
 | 
				
			||||||
               res.set_chunked_content_provider(
 | 
					               res.set_chunked_content_provider(
 | 
				
			||||||
                   [](size_t /*offset*/, DataSink &sink) {
 | 
					                   "text/plain", [](size_t /*offset*/, DataSink &sink) {
 | 
				
			||||||
                     EXPECT_TRUE(sink.is_writable());
 | 
					                     EXPECT_TRUE(sink.is_writable());
 | 
				
			||||||
                     sink.os << "123";
 | 
					                     sink.os << "123";
 | 
				
			||||||
                     sink.os << "456";
 | 
					                     sink.os << "456";
 | 
				
			||||||
@@ -898,6 +898,7 @@ protected:
 | 
				
			|||||||
             [&](const Request & /*req*/, Response &res) {
 | 
					             [&](const Request & /*req*/, Response &res) {
 | 
				
			||||||
               auto i = new int(0);
 | 
					               auto i = new int(0);
 | 
				
			||||||
               res.set_chunked_content_provider(
 | 
					               res.set_chunked_content_provider(
 | 
				
			||||||
 | 
					                   "text/plain",
 | 
				
			||||||
                   [i](size_t /*offset*/, DataSink &sink) {
 | 
					                   [i](size_t /*offset*/, DataSink &sink) {
 | 
				
			||||||
                     EXPECT_TRUE(sink.is_writable());
 | 
					                     EXPECT_TRUE(sink.is_writable());
 | 
				
			||||||
                     switch (*i) {
 | 
					                     switch (*i) {
 | 
				
			||||||
@@ -914,7 +915,8 @@ protected:
 | 
				
			|||||||
        .Get("/streamed",
 | 
					        .Get("/streamed",
 | 
				
			||||||
             [&](const Request & /*req*/, Response &res) {
 | 
					             [&](const Request & /*req*/, Response &res) {
 | 
				
			||||||
               res.set_content_provider(
 | 
					               res.set_content_provider(
 | 
				
			||||||
                   6, [](size_t offset, size_t /*length*/, DataSink &sink) {
 | 
					                   6, "text/plain",
 | 
				
			||||||
 | 
					                   [](size_t offset, size_t /*length*/, DataSink &sink) {
 | 
				
			||||||
                     sink.os << (offset < 3 ? "a" : "b");
 | 
					                     sink.os << (offset < 3 ? "a" : "b");
 | 
				
			||||||
                     return true;
 | 
					                     return true;
 | 
				
			||||||
                   });
 | 
					                   });
 | 
				
			||||||
@@ -923,7 +925,7 @@ protected:
 | 
				
			|||||||
             [&](const Request & /*req*/, Response &res) {
 | 
					             [&](const Request & /*req*/, Response &res) {
 | 
				
			||||||
               auto data = new std::string("abcdefg");
 | 
					               auto data = new std::string("abcdefg");
 | 
				
			||||||
               res.set_content_provider(
 | 
					               res.set_content_provider(
 | 
				
			||||||
                   data->size(),
 | 
					                   data->size(), "text/plain",
 | 
				
			||||||
                   [data](size_t offset, size_t length, DataSink &sink) {
 | 
					                   [data](size_t offset, size_t length, DataSink &sink) {
 | 
				
			||||||
                     EXPECT_TRUE(sink.is_writable());
 | 
					                     EXPECT_TRUE(sink.is_writable());
 | 
				
			||||||
                     size_t DATA_CHUNK_SIZE = 4;
 | 
					                     size_t DATA_CHUNK_SIZE = 4;
 | 
				
			||||||
@@ -938,7 +940,7 @@ protected:
 | 
				
			|||||||
        .Get("/streamed-cancel",
 | 
					        .Get("/streamed-cancel",
 | 
				
			||||||
             [&](const Request & /*req*/, Response &res) {
 | 
					             [&](const Request & /*req*/, Response &res) {
 | 
				
			||||||
               res.set_content_provider(
 | 
					               res.set_content_provider(
 | 
				
			||||||
                   size_t(-1),
 | 
					                   size_t(-1), "text/plain",
 | 
				
			||||||
                   [](size_t /*offset*/, size_t /*length*/, DataSink &sink) {
 | 
					                   [](size_t /*offset*/, size_t /*length*/, DataSink &sink) {
 | 
				
			||||||
                     EXPECT_TRUE(sink.is_writable());
 | 
					                     EXPECT_TRUE(sink.is_writable());
 | 
				
			||||||
                     sink.os << "data_chunk";
 | 
					                     sink.os << "data_chunk";
 | 
				
			||||||
@@ -1144,7 +1146,7 @@ protected:
 | 
				
			|||||||
                EXPECT_EQ(req.body, "content");
 | 
					                EXPECT_EQ(req.body, "content");
 | 
				
			||||||
              })
 | 
					              })
 | 
				
			||||||
        .Get("/last-request",
 | 
					        .Get("/last-request",
 | 
				
			||||||
             [&](const Request & req, Response &/*res*/) {
 | 
					             [&](const Request &req, Response & /*res*/) {
 | 
				
			||||||
               EXPECT_EQ("close", req.get_header_value("Connection"));
 | 
					               EXPECT_EQ("close", req.get_header_value("Connection"));
 | 
				
			||||||
             })
 | 
					             })
 | 
				
			||||||
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
					#ifdef CPPHTTPLIB_ZLIB_SUPPORT
 | 
				
			||||||
@@ -2022,6 +2024,25 @@ TEST_F(ServerTest, PutContentWithDeflate) {
 | 
				
			|||||||
  EXPECT_EQ("PUT", res->body);
 | 
					  EXPECT_EQ("PUT", res->body);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(ServerTest, GetStreamedChunkedWithGzip) {
 | 
				
			||||||
 | 
					  httplib::Headers headers;
 | 
				
			||||||
 | 
					  headers.emplace("Accept-Encoding", "gzip, deflate");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto res = cli_.Get("/streamed-chunked", headers);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(res != nullptr);
 | 
				
			||||||
 | 
					  EXPECT_EQ(200, res->status);
 | 
				
			||||||
 | 
					  EXPECT_EQ(std::string("123456789"), res->body);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(ServerTest, GetStreamedChunkedWithGzip2) {
 | 
				
			||||||
 | 
					  httplib::Headers headers;
 | 
				
			||||||
 | 
					  headers.emplace("Accept-Encoding", "gzip, deflate");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto res = cli_.Get("/streamed-chunked2", headers);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(res != nullptr);
 | 
				
			||||||
 | 
					  EXPECT_EQ(200, res->status);
 | 
				
			||||||
 | 
					  EXPECT_EQ(std::string("123456789"), res->body);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(ServerTest, Patch) {
 | 
					TEST_F(ServerTest, Patch) {
 | 
				
			||||||
@@ -2513,9 +2534,9 @@ TEST(ServerStopTest, StopServerWithChunkedTransmission) {
 | 
				
			|||||||
  Server svr;
 | 
					  Server svr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  svr.Get("/events", [](const Request & /*req*/, Response &res) {
 | 
					  svr.Get("/events", [](const Request & /*req*/, Response &res) {
 | 
				
			||||||
    res.set_header("Content-Type", "text/event-stream");
 | 
					 | 
				
			||||||
    res.set_header("Cache-Control", "no-cache");
 | 
					    res.set_header("Cache-Control", "no-cache");
 | 
				
			||||||
    res.set_chunked_content_provider([](size_t offset, DataSink &sink) {
 | 
					    res.set_chunked_content_provider("text/event-stream", [](size_t offset,
 | 
				
			||||||
 | 
					                                                             DataSink &sink) {
 | 
				
			||||||
      char buffer[27];
 | 
					      char buffer[27];
 | 
				
			||||||
      auto size = static_cast<size_t>(sprintf(buffer, "data:%ld\n\n", offset));
 | 
					      auto size = static_cast<size_t>(sprintf(buffer, "data:%ld\n\n", offset));
 | 
				
			||||||
      sink.write(buffer, size);
 | 
					      sink.write(buffer, size);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user