From c82d1e52cc68e14169070d8d1346360cddcd3f27 Mon Sep 17 00:00:00 2001
From: yhirose <yuji.hirose.bug@gmail.com>
Date: Wed, 16 Mar 2022 10:55:56 -0400
Subject: [PATCH] Fix #1214

---
 httplib.h    | 13 +++++++++++--
 test/test.cc | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/httplib.h b/httplib.h
index 294e035..6d64bdf 100644
--- a/httplib.h
+++ b/httplib.h
@@ -4965,6 +4965,14 @@ inline bool Server::parse_request_line(const char *s, Request &req) {
   if (req.version != "HTTP/1.1" && req.version != "HTTP/1.0") { return false; }
 
   {
+    // Skip URL fragment
+    for (size_t i = 0; i < len; i++) {
+      if (req.target[i] == '#') {
+        req.target.erase(i);
+        break;
+      }
+    }
+
     size_t count = 0;
 
     detail::split(req.target.data(), req.target.data() + req.target.size(), '?',
@@ -7269,8 +7277,9 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
     SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION);
 
     // add default password callback before opening encrypted private key
-    if (private_key_password != nullptr && (private_key_password[0] != '\0') ) {
-      SSL_CTX_set_default_passwd_cb_userdata(ctx_, (char *)private_key_password);
+    if (private_key_password != nullptr && (private_key_password[0] != '\0')) {
+      SSL_CTX_set_default_passwd_cb_userdata(ctx_,
+                                             (char *)private_key_password);
     }
 
     if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 ||
diff --git a/test/test.cc b/test/test.cc
index 84e6dee..b86ce08 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -1416,6 +1416,35 @@ TEST(InvalidFormatTest, StatusCode) {
   ASSERT_FALSE(svr.is_running());
 }
 
+TEST(URLFragmentTest, WithFragment) {
+  Server svr;
+
+  svr.Get("/hi",
+          [](const Request &req, Response &/*res*/) {
+            EXPECT_TRUE(req.target == "/hi");
+          });
+
+  auto thread = std::thread([&]() { svr.listen(HOST, PORT); });
+
+  std::this_thread::sleep_for(std::chrono::seconds(1));
+
+  {
+    Client cli(HOST, PORT);
+
+    auto res = cli.Get("/hi#key1=val1=key2=val2");
+    EXPECT_TRUE(res);
+    EXPECT_EQ(200, res->status);
+
+    res = cli.Get("/hi%23key1=val1=key2=val2");
+    EXPECT_TRUE(res);
+    EXPECT_EQ(404, res->status);
+  }
+
+  svr.stop();
+  thread.join();
+  ASSERT_FALSE(svr.is_running());
+}
+
 class ServerTest : public ::testing::Test {
 protected:
   ServerTest()
@@ -4791,7 +4820,6 @@ TEST(HttpToHttpsRedirectTest, CertFile) {
   t.join();
   t2.join();
 }
-#endif
 
 TEST(MultipartFormDataTest, LargeData) {
   SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
@@ -4855,3 +4883,5 @@ TEST(MultipartFormDataTest, LargeData) {
   svr.stop();
   t.join();
 }
+#endif
+