Allow to cancel asynchronous HTTP requests (#332)

Usage:

	auto args = this->httpClient.createRequest(url, method);
	httpClient.performRequest(args, ...);
	[...]
	// Oops, we don't actually want to complete the request!
	args->cancel = true;
This commit is contained in:
Martin Natano
2021-12-21 08:01:55 +01:00
committed by GitHub
parent 688f85fda6
commit 66cd29e747
4 changed files with 81 additions and 11 deletions

View File

@ -241,17 +241,21 @@ namespace ix
std::string errMsg;
// Make a cancellation object dealing with connection timeout
auto isCancellationRequested =
makeCancellationRequestWithTimeout(args->connectTimeout, _stop);
auto cancelled = makeCancellationRequestWithTimeout(args->connectTimeout, args->cancel);
auto isCancellationRequested = [&]() {
return cancelled() || _stop;
};
bool success = _socket->connect(host, port, errMsg, isCancellationRequested);
if (!success)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::CannotConnect;
std::stringstream ss;
ss << "Cannot connect to url: " << url << " / error : " << errMsg;
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::CannotConnect,
errorCode,
headers,
payload,
ss.str(),
@ -260,7 +264,7 @@ namespace ix
}
// Make a new cancellation object dealing with transfer timeout
isCancellationRequested = makeCancellationRequestWithTimeout(args->transferTimeout, _stop);
cancelled = makeCancellationRequestWithTimeout(args->transferTimeout, args->cancel);
if (args->verbose)
{
@ -277,10 +281,11 @@ namespace ix
if (!_socket->writeBytes(req, isCancellationRequested))
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::SendError;
std::string errorMsg("Cannot send request");
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::SendError,
errorCode,
headers,
payload,
errorMsg,
@ -296,10 +301,11 @@ namespace ix
if (!lineValid)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::CannotReadStatusLine;
std::string errorMsg("Cannot retrieve status line");
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::CannotReadStatusLine,
errorCode,
headers,
payload,
errorMsg,
@ -333,10 +339,11 @@ namespace ix
if (!headersValid)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::HeaderParsingError;
std::string errorMsg("Cannot parse http headers");
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::HeaderParsingError,
errorCode,
headers,
payload,
errorMsg,
@ -405,10 +412,11 @@ namespace ix
contentLength, args->onProgressCallback, isCancellationRequested);
if (!chunkResult.first)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::ChunkReadError;
errorMsg = "Cannot read chunk";
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::ChunkReadError,
errorCode,
headers,
payload,
errorMsg,
@ -424,6 +432,7 @@ namespace ix
while (true)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::ChunkReadError;
lineResult = _socket->readLine(isCancellationRequested);
line = lineResult.second;
@ -431,7 +440,7 @@ namespace ix
{
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::ChunkReadError,
errorCode,
headers,
payload,
errorMsg,
@ -458,10 +467,11 @@ namespace ix
(size_t) chunkSize, args->onProgressCallback, isCancellationRequested);
if (!chunkResult.first)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::ChunkReadError;
errorMsg = "Cannot read chunk";
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::ChunkReadError,
errorCode,
headers,
payload,
errorMsg,
@ -475,9 +485,10 @@ namespace ix
if (!lineResult.first)
{
auto errorCode = args->cancel ? HttpErrorCode::Cancelled : HttpErrorCode::ChunkReadError;
return std::make_shared<HttpResponse>(code,
description,
HttpErrorCode::ChunkReadError,
errorCode,
headers,
payload,
errorMsg,