Commit 49e2bb92 authored by Jens Moeller's avatar Jens Moeller
Browse files

Support asynchronous requests with internal I/O context

parent 571fe8b0
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ namespace SimpleWeb {
    /// If you reuse the io_service for other tasks, use the asynchronous request functions instead.
    /// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead.
    std::shared_ptr<Response> request(const std::string &method, const std::string &path = {"/"}, string_view content = {}, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) {
      start_internal_io_service_handler_thread();
      std::promise<std::shared_ptr<Response>> response_promise;
      std::future<std::shared_ptr<Response>> response_future = response_promise.get_future();
      std::shared_ptr<Response> response;
@@ -251,6 +252,7 @@ namespace SimpleWeb {
    /// If you reuse the io_service for other tasks, use the asynchronous request functions instead.
    /// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead.
    std::shared_ptr<Response> request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) {
      start_internal_io_service_handler_thread();
      std::promise<std::shared_ptr<Response>> response_promise;
      std::future<std::shared_ptr<Response>> response_future = response_promise.get_future();
      std::shared_ptr<Response> response;
@@ -465,8 +467,7 @@ namespace SimpleWeb {
      port = parsed_host_port.second;
    }

    std::shared_ptr<Connection> get_connection() noexcept {
      std::shared_ptr<Connection> connection;
    void start_internal_io_service_handler_thread() noexcept {
      LockGuard lock(connections_mutex);

      if(!io_service) {
@@ -477,6 +478,15 @@ namespace SimpleWeb {
          io_service->run();
        }));
      }
    }

    std::shared_ptr<Connection> get_connection() noexcept {
      std::shared_ptr<Connection> connection;
      LockGuard lock(connections_mutex);

      if(!io_service) {
        io_service = std::make_shared<asio::io_service>();
      }

      for(auto it = connections.begin(); it != connections.end(); ++it) {
        if(!(*it)->in_use) {
+22 −15
Original line number Diff line number Diff line
@@ -389,12 +389,16 @@ int main() {

  // Test large responses
  {
    HttpClient client("localhost:8080");
    client.config.max_response_streambuf_size = 400;
    // Don't mix synchronous and asynchronous on the same client
    HttpClient sync_request_client("localhost:8080");
    HttpClient async_request_client("localhost:8080");
    sync_request_client.config.max_response_streambuf_size = 400;
    async_request_client.config.max_response_streambuf_size = 400;
    async_request_client.io_service = std::make_shared<SimpleWeb::io_context>();
    {
      bool thrown = false;
      try {
        auto r = client.request("GET", "/long-response");
        auto r = sync_request_client.request("GET", "/long-response");
      }
      catch(...) {
        thrown = true;
@@ -405,7 +409,7 @@ int main() {
      size_t calls = 0;
      bool end = false;
      std::string content;
      client.request("GET", "/long-response", [&calls, &content, &end](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
      async_request_client.request("GET", "/long-response", [&calls, &content, &end](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
        ASSERT(!ec);
        content += response->content.string();
        calls++;
@@ -413,8 +417,8 @@ int main() {
          ASSERT(response->content.end == false);
        end = response->content.end;
      });
      SimpleWeb::restart(*client.io_service);
      client.io_service->run();
      SimpleWeb::restart(*async_request_client.io_service);
      async_request_client.io_service->run();
      ASSERT(content == long_response);
      ASSERT(calls > 2);
      ASSERT(end == true);
@@ -422,15 +426,15 @@ int main() {
    {
      size_t calls = 0;
      std::string content;
      client.request("GET", "/long-response", [&calls, &content](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
      async_request_client.request("GET", "/long-response", [&calls, &content](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
        if(calls == 0)
          ASSERT(!ec);
        content += response->content.string();
        calls++;
        response->close();
      });
      SimpleWeb::restart(*client.io_service);
      client.io_service->run();
      SimpleWeb::restart(*async_request_client.io_service);
      async_request_client.io_service->run();
      ASSERT(!content.empty());
      ASSERT(calls >= 2);
    }
@@ -438,12 +442,15 @@ int main() {

  // Test client timeout
  {
    HttpClient client("localhost:8080");
    client.config.timeout = 2;
    // Don't mix synchronous and asynchronous on the same client
    HttpClient sync_request_client("localhost:8080");
    HttpClient async_request_client("localhost:8080");
    sync_request_client.config.timeout = 2;
    async_request_client.config.timeout = 2;
    {
      bool thrown = false;
      try {
        auto r = client.request("GET", "/work");
        auto r = sync_request_client.request("GET", "/work");
      }
      catch(...) {
        thrown = true;
@@ -452,12 +459,12 @@ int main() {
    }
    {
      bool call = false;
      client.request("GET", "/work", [&call](shared_ptr<HttpClient::Response> /*response*/, const SimpleWeb::error_code &ec) {
      async_request_client.request("GET", "/work", [&call](shared_ptr<HttpClient::Response> /*response*/, const SimpleWeb::error_code &ec) {
        ASSERT(ec);
        call = true;
      });
      SimpleWeb::restart(*client.io_service);
      client.io_service->run();
      SimpleWeb::restart(*async_request_client.io_service);
      async_request_client.io_service->run();
      ASSERT(call);
    }
  }