Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request Lost when using SSL #1825

Open
nanjo712 opened this issue Apr 20, 2024 · 4 comments
Open

Request Lost when using SSL #1825

nanjo712 opened this issue Apr 20, 2024 · 4 comments

Comments

@nanjo712
Copy link

I am trying to build an HTTP server with SSL using httplib, and I have generated an SSL certificate using OpenSSL, something like this: httplib::SSLServer server("server.crt", "server.key");. When I send a large number of requests using Postman for testing, two-thirds of the requests are consistently lost. Strangely, this two-thirds ratio is almost stable, meaning that no matter how many threads I use, each thread will lose two-thirds of its requests. What's even more peculiar is that if I start 10 threads at the same time and only send one request per thread, all requests receive responses.

This phenomenon is not limited to local HTTP requests; remote requests have the same issue, exhibiting the exact same behavior. However, once I disable SSL, all instances of request loss disappear.

server.Get("/username",
               [&](const httplib::Request &req, httplib::Response &res)
               {
                   std::string token = req.get_header_value("Authorization");
                   if (token.find("Bearer ") == 0)
                   {
                       token.erase(0, 7);
                   }
                   else
                   {
                       res.status = 400;
                       res.set_content("Invalid token", "text/plain");
                       return;
                   }
                   auto user = user_manager.get_user(token);
                   if (user)
                   {
                       spdlog::info("Username retrieved: {}", user->get_username());
                       res.status = 200;
                       res.set_content(user->get_username(), "text/plain");
                   }
                   else
                   {
                       spdlog::warn("Invalid token: {}", token);
                       res.status = 400;
                       res.set_content("Invalid token", "text/plain");
                   }
               });
@yhirose
Copy link
Owner

yhirose commented Apr 21, 2024

@nanjo712 could you make a unit test that can reproduce the problem in test/test.cc with httplib:: SSLServer and httplib::SSLClient? Then, I'll take a look at it. Thanks!

@nanjo712
Copy link
Author

I tried unit testing but was unable to reproduce the bug. When I attempted to test with Python and other languages, I did not encounter the same issue either. It seems that this problem only occurs with Postman.

TEST(SSLTest, SSLTest1) {
  SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
  ASSERT_TRUE(svr.is_valid());
  svr.Get("/hi", [](const Request & /*req*/, Response &res) {
    res.set_content("Hello World!", "text/plain");
  });

  std::thread t([&]() { svr.listen(HOST, 8443); });
  auto se = detail::scope_exit([&] {
    svr.stop();
    t.join();
    ASSERT_FALSE(svr.is_running());
  });

  svr.wait_until_ready();

  auto func = []() {
    SSLClient cli("localhost", 8443);
    cli.enable_server_certificate_verification(false);

    for (int i = 0; i < 100; i++) {
      auto res = cli.Get("/hi");
      ASSERT_TRUE(res);
      EXPECT_EQ(StatusCode::OK_200, res->status);
      EXPECT_EQ("Hello World!", res->body);
    }
  };

  std::vector<std::thread> threads;
  for (int i = 0; i < 10; i++) {
    threads.emplace_back(func);
  }
  for (auto &t : threads) {
    t.join();
  }
}

it will pass the test.

Perhaps this library has some compatibility issues with Postman

@nanjo712
Copy link
Author

GET https://localhost:8080/username
Error: read ECONNRESET
Request Headers
Content-Type: application/json
Accept: */*
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjoiNzRjNzQ4ZGUtMjlkYy00ZjIxLTkzNzUtMTVmMjc3N2JhMjdiIn0sImV4cCI6MTcxNDQ2NzA4NiwiaWF0IjoxNzE0NDYzNDg2LCJpc3MiOiJ3b3NoaXJlbiIsIm5iZiI6MTcxNDQ2MzQ4Nn0.fykvd3AVKYLE0PqGQ0h5owIXD-OYTkllKqqK9TyDs7c
User-Agent: PostmanRuntime/7.37.3
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

When Postman get an Error, it shows message like this.
This looks like the server closed the TCP connection and the client sent a new request before receiving the disconnection message

@nanjo712
Copy link
Author

If I remove the "Connection: keep-alive" from the header, this problem will disappear. I think that‘s the problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants