Отримання бінарних відповідей libcurl у C++ std::string
Передайте std::string як контекст зворотного виклику й додавайте явні лічильники байтів під час отримання бінарних даних із libcurl.
Проксі може успішно отримати HTML і все ж пошкодити зображення, копіюючи його в буфер C++. Перш ніж змінювати протокол проксі, перевірте зворотний виклик отримання та об'єкт, переданий як його контекст.
CURLOPT_WRITEDATA надає вказівник на зворотний виклик запису. Без власного зворотного виклику стандартний записувач libcurl очікує FILE *. Адреса на кшталт &response, де response — це std::string, має сенс лише тоді, коли ваш зворотний виклик приводить цей контекст назад до потрібного типу.
static size_t receive(char* data, size_t size,
size_t count, void* context) {
const size_t bytes = size * count;
auto* body = static_cast<std::string*>(context);
try {
body->append(data, bytes);
} catch (...) {
return 0;
}
return bytes;
}Зареєструйте обидві половини на простому дескрипторі, що використовується для передавання:
std::string response;
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, receive);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &response);Виклик append використовує передану кількість байтів. Дані зворотного виклику не завершуються нулем, і зображення може містити нульові байти; вимірювання через strlen втратило б частину тіла. Відповідь також може надходити через багато викликів різного розміру.
Повернення спожитої кількості байтів приймає фрагмент. Повернення іншої кількості перериває передавання з помилкою запису. Захист винятків не дає збою виділення пам'яті вийти за межі зворотного виклику C; викликач усе одно має перевірити результат передавання, перш ніж вважати response повним файлом.
Тримайте рядок живим, доки передавання не завершиться. Якщо асинхронний запис у сокет потім пересилає його вміст, тримайте ці байти живими, доки й цей запис не завершиться. Для великих відповідей обмежена потокова схема краща за накопичення всього тіла.