diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0353b0c..b0e0fda 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,7 @@
 
 	-------------------------------------------------------------------------------
 
-	After installation with Cmake, a find_package(httplib COMPONENTS OpenSSL ZLIB Brotli) is available.
+	After installation with Cmake, a find_package(httplib COMPONENTS OpenSSL ZLIB Brotli zstd) is available.
 	This creates a httplib::httplib target (if found and if listed components are supported).
 	It can be linked like so:
 
@@ -159,10 +159,26 @@ elseif(HTTPLIB_USE_BROTLI_IF_AVAILABLE)
 endif()
 
 if(HTTPLIB_REQUIRE_ZSTD)
-	find_package(zstd REQUIRED)
+	find_package(zstd)
+	if(NOT zstd_FOUND)
+		find_package(PkgConfig REQUIRED)
+		pkg_check_modules(zstd REQUIRED IMPORTED_TARGET libzstd)
+		add_library(zstd::libzstd ALIAS PkgConfig::zstd)
+	endif()
 	set(HTTPLIB_IS_USING_ZSTD TRUE)
 elseif(HTTPLIB_USE_ZSTD_IF_AVAILABLE)
 	find_package(zstd QUIET)
+	if(NOT zstd_FOUND)
+		find_package(PkgConfig QUIET)
+		if(PKG_CONFIG_FOUND)
+			pkg_check_modules(zstd QUIET IMPORTED_TARGET libzstd)
+
+			if(TARGET PkgConfig::zstd)
+				add_library(zstd::libzstd ALIAS PkgConfig::zstd)
+			endif()
+		endif()
+	endif()
+	# Both find_package and PkgConf set a XXX_FOUND var
 	set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
 endif()
 
diff --git a/cmake/httplibConfig.cmake.in b/cmake/httplibConfig.cmake.in
index bf57364..19dbe69 100644
--- a/cmake/httplibConfig.cmake.in
+++ b/cmake/httplibConfig.cmake.in
@@ -39,7 +39,25 @@ if(@HTTPLIB_IS_USING_BROTLI@)
 endif()
 
 if(@HTTPLIB_IS_USING_ZSTD@)
-	find_dependency(zstd)
+	set(httplib_fd_zstd_quiet_arg)
+	if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
+		set(httplib_fd_zstd_quiet_arg QUIET)
+	endif()
+	set(httplib_fd_zstd_required_arg)
+	if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
+		set(httplib_fd_zstd_required_arg REQUIRED)
+	endif()
+	find_package(zstd QUIET)
+	if(NOT zstd_FOUND)
+		find_package(PkgConfig ${httplib_fd_zstd_quiet_arg} ${httplib_fd_zstd_required_arg})
+		if(PKG_CONFIG_FOUND)
+			pkg_check_modules(zstd ${httplib_fd_zstd_quiet_arg} ${httplib_fd_zstd_required_arg} IMPORTED_TARGET libzstd)
+
+			if(TARGET PkgConfig::zstd)
+				add_library(zstd::libzstd ALIAS PkgConfig::zstd)
+			endif()
+		endif()
+	endif()
 	set(httplib_zstd_FOUND ${zstd_FOUND})
 endif()
 
diff --git a/httplib.h b/httplib.h
index 33d7f97..ae4507d 100644
--- a/httplib.h
+++ b/httplib.h
@@ -8,7 +8,7 @@
 #ifndef CPPHTTPLIB_HTTPLIB_H
 #define CPPHTTPLIB_HTTPLIB_H
 
-#define CPPHTTPLIB_VERSION "0.20.0"
+#define CPPHTTPLIB_VERSION "0.20.1"
 
 /*
  * Configuration
@@ -145,6 +145,10 @@
 #define CPPHTTPLIB_LISTEN_BACKLOG 5
 #endif
 
+#ifndef CPPHTTPLIB_MAX_LINE_LENGTH
+#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
+#endif
+
 /*
  * Headers
  */
@@ -188,6 +192,9 @@ using ssize_t = long;
 #include <winsock2.h>
 #include <ws2tcpip.h>
 
+// afunix.h uses types declared in winsock2.h, so has to be included after it.
+#include <afunix.h>
+
 #ifndef WSA_FLAG_NO_HANDLE_INHERIT
 #define WSA_FLAG_NO_HANDLE_INHERIT 0x80
 #endif
@@ -1080,8 +1087,7 @@ private:
   bool listen_internal();
 
   bool routing(Request &req, Response &res, Stream &strm);
-  bool handle_file_request(const Request &req, Response &res,
-                           bool head = false);
+  bool handle_file_request(const Request &req, Response &res);
   bool dispatch_request(Request &req, Response &res,
                         const Handlers &handlers) const;
   bool dispatch_request_for_content_reader(
@@ -2059,7 +2065,9 @@ template <size_t N> inline constexpr size_t str_len(const char (&)[N]) {
 }
 
 inline bool is_numeric(const std::string &str) {
-  return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
+  return !str.empty() &&
+         std::all_of(str.cbegin(), str.cend(),
+                     [](unsigned char c) { return std::isdigit(c); });
 }
 
 inline uint64_t get_header_value_u64(const Headers &headers,
@@ -3064,6 +3072,11 @@ inline bool stream_line_reader::getline() {
 #endif
 
   for (size_t i = 0;; i++) {
+    if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
+      // Treat exceptionally long lines as an error to
+      // prevent infinite loops/memory exhaustion
+      return false;
+    }
     char byte;
     auto n = strm_.read(&byte, 1);
 
@@ -3365,7 +3378,7 @@ private:
   time_t write_timeout_sec_;
   time_t write_timeout_usec_;
   time_t max_timeout_msec_;
-  const std::chrono::time_point<std::chrono::steady_clock> start_time;
+  const std::chrono::time_point<std::chrono::steady_clock> start_time_;
 
   std::vector<char> read_buff_;
   size_t read_buff_off_ = 0;
@@ -3403,7 +3416,7 @@ private:
   time_t write_timeout_sec_;
   time_t write_timeout_usec_;
   time_t max_timeout_msec_;
-  const std::chrono::time_point<std::chrono::steady_clock> start_time;
+  const std::chrono::time_point<std::chrono::steady_clock> start_time_;
 };
 #endif
 
@@ -3538,7 +3551,6 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
     hints.ai_flags = socket_flags;
   }
 
-#ifndef _WIN32
   if (hints.ai_family == AF_UNIX) {
     const auto addrlen = host.length();
     if (addrlen > sizeof(sockaddr_un::sun_path)) { return INVALID_SOCKET; }
@@ -3562,11 +3574,19 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
           sizeof(addr) - sizeof(addr.sun_path) + addrlen);
 
 #ifndef SOCK_CLOEXEC
+#ifndef _WIN32
       fcntl(sock, F_SETFD, FD_CLOEXEC);
+#endif
 #endif
 
       if (socket_options) { socket_options(sock); }
 
+#ifdef _WIN32
+      // Setting SO_REUSEADDR seems not to work well with AF_UNIX on windows, so
+      // remove the option.
+      detail::set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 0);
+#endif
+
       bool dummy;
       if (!bind_or_connect(sock, hints, dummy)) {
         close_socket(sock);
@@ -3575,7 +3595,6 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
     }
     return sock;
   }
-#endif
 
   auto service = std::to_string(port);
 
@@ -6046,6 +6065,8 @@ inline void calc_actual_timeout(time_t max_timeout_msec, time_t duration_msec,
   auto actual_timeout_msec =
       (std::min)(max_timeout_msec - duration_msec, timeout_msec);
 
+  if (actual_timeout_msec < 0) { actual_timeout_msec = 0; }
+
   actual_timeout_sec = actual_timeout_msec / 1000;
   actual_timeout_usec = (actual_timeout_msec % 1000) * 1000;
 }
@@ -6060,7 +6081,7 @@ inline SocketStream::SocketStream(
       read_timeout_usec_(read_timeout_usec),
       write_timeout_sec_(write_timeout_sec),
       write_timeout_usec_(write_timeout_usec),
-      max_timeout_msec_(max_timeout_msec), start_time(start_time),
+      max_timeout_msec_(max_timeout_msec), start_time_(start_time),
       read_buff_(read_buff_size_, 0) {}
 
 inline SocketStream::~SocketStream() = default;
@@ -6158,7 +6179,7 @@ inline socket_t SocketStream::socket() const { return sock_; }
 
 inline time_t SocketStream::duration() const {
   return std::chrono::duration_cast<std::chrono::milliseconds>(
-             std::chrono::steady_clock::now() - start_time)
+             std::chrono::steady_clock::now() - start_time_)
       .count();
 }
 
@@ -6858,8 +6879,7 @@ Server::read_content_core(Stream &strm, Request &req, Response &res,
   return true;
 }
 
-inline bool Server::handle_file_request(const Request &req, Response &res,
-                                        bool head) {
+inline bool Server::handle_file_request(const Request &req, Response &res) {
   for (const auto &entry : base_dirs_) {
     // Prefix match
     if (!req.path.compare(0, entry.mount_point.size(), entry.mount_point)) {
@@ -6892,7 +6912,7 @@ inline bool Server::handle_file_request(const Request &req, Response &res,
                 return true;
               });
 
-          if (!head && file_request_handler_) {
+          if (req.method != "HEAD" && file_request_handler_) {
             file_request_handler_(req, res);
           }
 
@@ -7026,9 +7046,8 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm) {
   }
 
   // File handler
-  auto is_head_request = req.method == "HEAD";
-  if ((req.method == "GET" || is_head_request) &&
-      handle_file_request(req, res, is_head_request)) {
+  if ((req.method == "GET" || req.method == "HEAD") &&
+      handle_file_request(req, res)) {
     return true;
   }
 
@@ -7318,8 +7337,9 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
   }
 
   // Setup `is_connection_closed` method
-  req.is_connection_closed = [&]() {
-    return !detail::is_socket_alive(strm.socket());
+  auto sock = strm.socket();
+  req.is_connection_closed = [sock]() {
+    return !detail::is_socket_alive(sock);
   };
 
   // Routing
@@ -9200,7 +9220,7 @@ inline SSLSocketStream::SSLSocketStream(
       read_timeout_usec_(read_timeout_usec),
       write_timeout_sec_(write_timeout_sec),
       write_timeout_usec_(write_timeout_usec),
-      max_timeout_msec_(max_timeout_msec), start_time(start_time) {
+      max_timeout_msec_(max_timeout_msec), start_time_(start_time) {
   SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY);
 }
 
@@ -9306,7 +9326,7 @@ inline socket_t SSLSocketStream::socket() const { return sock_; }
 
 inline time_t SSLSocketStream::duration() const {
   return std::chrono::duration_cast<std::chrono::milliseconds>(
-             std::chrono::steady_clock::now() - start_time)
+             std::chrono::steady_clock::now() - start_time_)
       .count();
 }
 
diff --git a/test/test.cc b/test/test.cc
index acbd11a..a57b7c9 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -43,6 +43,10 @@ const int PORT = 1234;
 const string LONG_QUERY_VALUE = string(25000, '@');
 const string LONG_QUERY_URL = "/long-query-value?key=" + LONG_QUERY_VALUE;
 
+const string TOO_LONG_QUERY_VALUE = string(35000, '@');
+const string TOO_LONG_QUERY_URL =
+    "/too-long-query-value?key=" + TOO_LONG_QUERY_VALUE;
+
 const std::string JSON_DATA = "{\"hello\":\"world\"}";
 
 const string LARGE_DATA = string(1024 * 1024 * 100, '@'); // 100MB
@@ -70,7 +74,6 @@ static void read_file(const std::string &path, std::string &out) {
   fs.read(&out[0], static_cast<std::streamsize>(size));
 }
 
-#ifndef _WIN32
 class UnixSocketTest : public ::testing::Test {
 protected:
   void TearDown() override { std::remove(pathname_.c_str()); }
@@ -167,6 +170,7 @@ TEST_F(UnixSocketTest, abstract) {
 }
 #endif
 
+#ifndef _WIN32
 TEST(SocketStream, wait_writable_UNIX) {
   int fds[2];
   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, fds));
@@ -2867,6 +2871,11 @@ protected:
                EXPECT_EQ(LONG_QUERY_URL, req.target);
                EXPECT_EQ(LONG_QUERY_VALUE, req.get_param_value("key"));
              })
+        .Get("/too-long-query-value",
+             [&](const Request &req, Response & /*res*/) {
+               EXPECT_EQ(TOO_LONG_QUERY_URL, req.target);
+               EXPECT_EQ(TOO_LONG_QUERY_VALUE, req.get_param_value("key"));
+             })
         .Get("/array-param",
              [&](const Request &req, Response & /*res*/) {
                EXPECT_EQ(3u, req.get_param_value_count("array"));
@@ -3655,6 +3664,13 @@ TEST_F(ServerTest, LongQueryValue) {
   EXPECT_EQ(StatusCode::UriTooLong_414, res->status);
 }
 
+TEST_F(ServerTest, TooLongQueryValue) {
+  auto res = cli_.Get(TOO_LONG_QUERY_URL.c_str());
+
+  ASSERT_FALSE(res);
+  EXPECT_EQ(Error::Read, res.error());
+}
+
 TEST_F(ServerTest, TooLongHeader) {
   Request req;
   req.method = "GET";
@@ -8623,7 +8639,7 @@ TEST(MaxTimeoutTest, ContentStream) {
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 TEST(MaxTimeoutTest, ContentStreamSSL) {
   time_t timeout = 2000;
-  time_t threshold = 500; // SSL_shutdown is slow on some operating systems.
+  time_t threshold = 1200; // SSL_shutdown is slow on some operating systems.
 
   SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);