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
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Try to resend request if connection has been closed.
v.mishanin committed Feb 8, 2022
commit 66741d3e554143a75072749093bce276e203fce0
16 changes: 8 additions & 8 deletions Release/src/http/client/http_client_asio.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
@@ -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);
}
}

@@ -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);
}
}

@@ -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))
{
@@ -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;
}

@@ -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;

@@ -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);
}
}

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
@@ -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);