Add support for streaming transfers

This change adds onChunkCallback to the request. If defined it will be
called repeatedly with the incoming data. This allows to process data on
the go or write it to disk instead of accumulating the data in memory.

Submitted upstream:
https://github.com/machinezone/IXWebSocket/pull/353
This commit is contained in:
Martin Natano
2022-03-12 14:18:48 -08:00
committed by teejusb
parent bb8fc0f4c2
commit 394bc93915
8 changed files with 120 additions and 17 deletions
+68
View File
@@ -5,6 +5,7 @@
*/
#include "catch.hpp"
#include <cstdint>
#include <iostream>
#include <ixwebsocket/IXHttpClient.h>
@@ -274,4 +275,71 @@ TEST_CASE("http_client", "[http]")
std::cerr << "Done" << std::endl;
REQUIRE(errorCode == HttpErrorCode::Cancelled);
}
SECTION("Async API, streaming transfer")
{
bool async = true;
HttpClient httpClient(async);
WebSocketHttpHeaders headers;
SocketTLSOptions tlsOptions;
tlsOptions.caFile = "cacert.pem";
httpClient.setTLSOptions(tlsOptions);
std::string url("http://speedtest.belwue.net/random-100M");
auto args = httpClient.createRequest(url);
args->extraHeaders = headers;
args->connectTimeout = 60;
args->transferTimeout = 120;
args->followRedirects = true;
args->maxRedirects = 10;
args->verbose = true;
args->compress = false;
args->logger = [](const std::string& msg) { std::cout << msg; };
args->onProgressCallback = [](int current, int total) -> bool {
std::cerr << "\r"
<< "Downloaded " << current << " bytes out of " << total;
return true;
};
// compute Adler-32 checksum of received data
uint32_t a = 1, b = 0;
args->onChunkCallback = [&](const std::string& data) {
for (const char c: data)
{
a = (a + (unsigned char)c) % 65521;
b = (b + a) % 65521;
}
};
std::atomic<bool> requestCompleted(false);
std::atomic<HttpErrorCode> errorCode(HttpErrorCode::Invalid);
std::atomic<int> statusCode(0);
httpClient.performRequest(
args, [&](const HttpResponsePtr& response) {
errorCode = response->errorCode;
statusCode = response->statusCode;
requestCompleted = true;
});
int wait = 0;
while (wait < 120000)
{
if (requestCompleted) break;
std::chrono::duration<double, std::milli> duration(10);
std::this_thread::sleep_for(duration);
wait += 10;
}
std::cerr << "Done" << std::endl;
REQUIRE(errorCode == HttpErrorCode::Ok);
REQUIRE(statusCode == 200);
// compare checksum with a known good value
uint32_t checksum = (b << 16) | a;
REQUIRE(checksum == 1440194471);
}
}