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

Try to resend request if connection has been closed. #1682

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 8 additions & 8 deletions Release/src/http/client/http_client_asio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class asio_connection

// These errors tell if connection was closed.
if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec) ||
(boost::asio::error::connection_aborted == ec))
(boost::asio::error::connection_aborted == ec) || (boost::asio::error::broken_pipe == ec))
{
return true;
}
Expand Down Expand Up @@ -710,7 +710,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
}
else
{
m_context->handle_failed_read_status_line(ec, "Failed to read HTTP status line from proxy");
m_context->restore_closed_connection(ec, "Failed to read HTTP status line from proxy", httpclient_errorcode_context::readheader);
}
}

Expand Down Expand Up @@ -1300,7 +1300,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
}
else
{
report_error("Failed to write request body", ec, httpclient_errorcode_context::writebody);
restore_closed_connection(ec, "Failed to write request body", httpclient_errorcode_context::writebody);
}
}

Expand Down Expand Up @@ -1344,11 +1344,12 @@ class asio_context final : public request_context, public std::enable_shared_fro
}
else
{
handle_failed_read_status_line(ec, "Failed to read HTTP status line");
restore_closed_connection(ec, "Failed to read HTTP status line", httpclient_errorcode_context::readheader);
}
}

void handle_failed_read_status_line(const boost::system::error_code& ec, const char* generic_error_message)
void restore_closed_connection(
const boost::system::error_code& ec, const char* generic_error_message, httpclient_errorcode_context error_context)
{
if (m_connection->was_reused_and_closed_by_server(ec))
{
Expand Down Expand Up @@ -1385,7 +1386,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
{
report_error("cannot rewind input stream for connection re-establishment",
ec,
httpclient_errorcode_context::readheader);
error_context);
return;
}

Expand All @@ -1402,7 +1403,6 @@ class asio_context final : public request_context, public std::enable_shared_fro
return;
}
}

new_ctx->m_request_completion = m_request_completion;
new_ctx->m_cancellationRegistration = m_cancellationRegistration;

Expand All @@ -1412,7 +1412,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
}
else
{
report_error(generic_error_message, ec, httpclient_errorcode_context::readheader);
report_error(generic_error_message, ec, error_context);
}
}

Expand Down
52 changes: 52 additions & 0 deletions Release/tests/functional/http/client/connections_and_errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,58 @@ SUITE(connections_and_errors)
VERIFY_THROWS(client.request(methods::GET).wait(), web::http::http_exception);
}

TEST_FIXTURE(uri_address, send_request_to_reopened_connection)
{
http_client_config config;
config.set_timeout(utility::seconds(1));

http_client client(m_uri, config);
{
// 1st request.
test_http_server::scoped_server server(m_uri);
auto t = server.server()->next_request().then([](test_request* p_request) {
p_request->reply(200);
});

// Send request.
auto response = client.request(methods::PUT);

// Wait for request
VERIFY_NO_THROWS(t.get());

// Wait for reply.
VERIFY_NO_THROWS(response.wait());

// Close server connection. For example, keep-alive timeout reason.
server.server()->close();
}

{
// 2nd. Send request to connection has been closed.

utility::string_t str_body(U("Hi, I'm reused connection"));
std::vector<unsigned char> raw_body(str_body.size() * sizeof(utility::char_t));
memcpy(&raw_body[0], &str_body[0], str_body.size() * sizeof(utility::char_t));

// Reopen connection.
test_http_server::scoped_server server(m_uri);
auto t = server.server()->next_request().then([&](test_request* p_request) {
VERIFY_ARE_EQUAL(p_request->m_body, raw_body);
p_request->reply(200);
});

// Try to send request with payload.
auto msg = http_request(methods::POST);
msg.set_body(str_body);
auto response = client.request(msg);

// Wait for request
VERIFY_NO_THROWS(t.get());

http_asserts::assert_response_equals(response.get(), status_codes::OK);
}
}

TEST_FIXTURE(uri_address, request_timeout)
{
test_http_server::scoped_server scoped(m_uri);
Expand Down