Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
http_download.hpp
Go to the documentation of this file.
1#pragma once
4#include <cstdint>
5
6#ifdef __clang__
7#pragma clang diagnostic push
8// -Wdeprecated-literal-operator is only available in Clang 18+, ignore unknown warnings for Apple Clang
9#pragma clang diagnostic ignored "-Wunknown-warning-option"
10#pragma clang diagnostic ignored "-Wdeprecated-literal-operator"
11#pragma clang diagnostic ignored "-Wunused-parameter"
12#pragma clang diagnostic ignored "-Wsign-conversion"
13#endif
14#ifdef __GNUC__
15#pragma GCC diagnostic push
16#pragma GCC diagnostic ignored "-Wunused-parameter"
17#endif
18#ifndef __wasm__
19#include <httplib.h>
20#endif
21#ifdef __GNUC__
22#pragma GCC diagnostic pop
23#endif
24#ifdef __clang__
25#pragma clang diagnostic pop
26#endif
27
28#include <chrono>
29#include <string>
30#include <thread>
31#include <vector>
32
33namespace bb::srs {
34
46inline std::vector<uint8_t> http_download([[maybe_unused]] const std::string& url,
47 [[maybe_unused]] size_t start_byte = 0,
48 [[maybe_unused]] size_t end_byte = 0)
49{
50#ifdef __wasm__
51 throw_or_abort("HTTP download not supported in WASM");
52#else
53 // Parse URL into host and path
54 size_t proto_end = url.find("://");
55 if (proto_end == std::string::npos) {
56 throw_or_abort("Invalid URL format: " + url);
57 }
58
59 size_t host_start = proto_end + 3;
60 size_t path_start = url.find('/', host_start);
61 if (path_start == std::string::npos) {
62 throw_or_abort("Invalid URL format: " + url);
63 }
64
65 std::string host = url.substr(host_start, path_start - host_start);
66 std::string path = url.substr(path_start);
67
68 // Create HTTP client (non-SSL)
69 httplib::Client cli("http://" + host);
70 cli.set_follow_location(true);
71 cli.set_connection_timeout(30);
72 cli.set_read_timeout(60);
73
74 // Prepare headers
75 httplib::Headers headers;
76 if (end_byte > 0 && end_byte >= start_byte) {
77 headers.emplace("Range", "bytes=" + std::to_string(start_byte) + "-" + std::to_string(end_byte));
78 }
79
80 constexpr int max_attempts = 3;
81 // Bound retry-induced latency: each retry attempt uses tighter timeouts than the first try
82 // so the worst-case extra time (backoffs + retry attempts) stays under ~15s.
83 // Math: backoff 1s + 2s + 2 retries * 5s timeout = 13s.
84 constexpr int retry_timeout_seconds = 5;
85
86 std::chrono::milliseconds backoff{ 1000 };
87 std::string last_error;
88 for (int attempt = 1; attempt <= max_attempts; ++attempt) {
89 if (attempt == 2) {
90 cli.set_connection_timeout(retry_timeout_seconds);
91 cli.set_read_timeout(retry_timeout_seconds);
92 }
93
94 auto res = cli.Get(path.c_str(), headers);
95
96 if (res && (res->status == 200 || res->status == 206)) {
97 const std::string& body = res->body;
98 return std::vector<uint8_t>(body.begin(), body.end());
99 }
100
101 bool retryable = false;
102 if (!res) {
103 last_error = httplib::to_string(res.error());
104 retryable = true;
105 } else {
106 last_error = "status " + std::to_string(res->status);
107 // Retry on 5xx and 429 (rate limit); other 4xx are client errors and won't change with retry.
108 retryable = res->status >= 500 || res->status == 429;
109 }
110
111 if (!retryable || attempt == max_attempts) {
112 throw_or_abort("HTTP request failed for " + url + ": " + last_error + " (after " + std::to_string(attempt) +
113 " attempt" + (attempt == 1 ? "" : "s") + ")");
114 }
115
116 vinfo("HTTP download of ", url, " failed (", last_error, "), retrying in ", backoff.count(), "ms");
117 std::this_thread::sleep_for(backoff);
118 backoff *= 2;
119 }
120 // Unreachable: loop above either returns on success or throws on the final attempt.
121 throw_or_abort("HTTP request failed for " + url + ": " + last_error);
122#endif
123}
124} // namespace bb::srs
#define vinfo(...)
Definition log.hpp:94
std::vector< uint8_t > http_download(const std::string &url, size_t start_byte=0, size_t end_byte=0)
Download data from a URL with optional Range header support.
std::string to_string(bb::avm2::ValueTag tag)
void throw_or_abort(std::string const &err)