Reset connection pool upon failure to read response (#4208)

* Reset connection pool upon failure to read response

* cspell

* format

* format

* CR
This commit is contained in:
Johannes Schönberger 2023-01-18 23:07:31 +01:00 committed by GitHub
parent d5e2ab88a9
commit 6e6ca66c26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 13 deletions

View File

@ -357,7 +357,8 @@ std::unique_ptr<RawResponse> CurlTransport::Send(Request& request, Context const
getConnectionOpenIntent++)
{
performing = session->Perform(context);
if (performing != CURLE_UNSUPPORTED_PROTOCOL && performing != CURLE_SEND_ERROR)
if (performing != CURLE_UNSUPPORTED_PROTOCOL && performing != CURLE_SEND_ERROR
&& performing != CURLE_RECV_ERROR)
{
break;
}
@ -454,7 +455,11 @@ CURLcode CurlSession::Perform(Context const& context)
}
Log::Write(Logger::Level::Verbose, LogMsgPrefix + "Parse server response");
ReadStatusLineAndHeadersFromRawResponse(context);
result = ReadStatusLineAndHeadersFromRawResponse(context);
if (result != CURLE_OK)
{
return result;
}
// non-PUT request are ready to be stream at this point. Only PUT request would start an uploading
// transfer where we want to maintain the `PERFORM` state.
@ -479,7 +484,11 @@ CURLcode CurlSession::Perform(Context const& context)
{
// If internal buffer has more data after the 100-continue means Server return an error.
// We don't need to upload body, just parse the response from Server and return
ReadStatusLineAndHeadersFromRawResponse(context, true);
result = ReadStatusLineAndHeadersFromRawResponse(context, true);
if (result != CURLE_OK)
{
return result;
}
m_sessionState = SessionState::STREAMING;
return result;
}
@ -493,7 +502,11 @@ CURLcode CurlSession::Perform(Context const& context)
}
Log::Write(Logger::Level::Verbose, LogMsgPrefix + "Upload completed. Parse server response");
ReadStatusLineAndHeadersFromRawResponse(context);
result = ReadStatusLineAndHeadersFromRawResponse(context);
if (result != CURLE_OK)
{
return result;
}
// If no throw at this point, the request is ready to stream.
// If any throw happened before this point, the state will remain as PERFORM.
m_sessionState = SessionState::STREAMING;
@ -801,7 +814,7 @@ void CurlSession::ParseChunkSize(Context const& context)
}
// Read status line plus headers to create a response with no body
void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
CURLcode CurlSession::ReadStatusLineAndHeadersFromRawResponse(
Context const& context,
bool reuseInternalBuffer)
{
@ -832,8 +845,8 @@ void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
if (bufferSize == 0)
{
// closed connection, prevent application from keep trying to pull more bytes from the wire
throw TransportException(
"Connection was closed by the server while trying to read a response");
Log::Write(Logger::Level::Error, "Failed to read from socket");
return CURLE_RECV_ERROR;
}
// returns the number of bytes parsed up to the body Start
bytesParsed = parser.Parse(this->m_readBuffer, bufferSize);
@ -860,7 +873,7 @@ void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
{
this->m_contentLength = 0;
this->m_bodyStartInBuffer = _detail::DefaultLibcurlReaderSize;
return;
return CURLE_OK;
}
// headers are already lowerCase at this point
@ -892,7 +905,7 @@ void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
{
this->m_contentLength
= static_cast<int64_t>(std::stoull(isContentLengthHeaderInResponse->second.data()));
return;
return CURLE_OK;
}
// No content-length from headers, check transfer-encoding
@ -918,14 +931,14 @@ void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
{
// closed connection, prevent application from keep trying to pull more bytes from the
// wire
throw TransportException(
"Connection was closed by the server while trying to read a response");
Log::Write(Logger::Level::Error, "Failed to read from socket");
return CURLE_RECV_ERROR;
}
this->m_bodyStartInBuffer = 0;
}
ParseChunkSize(context);
return;
return CURLE_OK;
}
}
/*
@ -935,6 +948,7 @@ void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
number of octets received prior to the server closing the
connection.
*/
return CURLE_OK;
}
/**

View File

@ -314,8 +314,10 @@ namespace Azure { namespace Core { namespace Http {
*
* @param context A context to control the request lifetime.
* @param reuseInternalBuffer Indicates whether the internal buffer should be reused.
*
* @return Curl code. CURLE_OK if successful, otherwise CURLE_RECV_ERROR.
*/
void ReadStatusLineAndHeadersFromRawResponse(
CURLcode ReadStatusLineAndHeadersFromRawResponse(
Context const& context,
bool reuseInternalBuffer = false);