Commit 947781c4 authored by Jørgen Lind's avatar Jørgen Lind
Browse files

Merge branch feature/jorgen.lind/curlPresign with refs/heads/master into...

Merge branch feature/jorgen.lind/curlPresign with refs/heads/master into refs/merge-requests/83/train
parents 4db0d9f3 9ac507fb
Pipeline #946 passed with stages
in 8 minutes and 4 seconds
......@@ -7,3 +7,5 @@ cpprestapi*
azure-storage-cpp*
pybind11-2.4.3
CMakeArtifacts*
curl*
libuv*
......@@ -4,6 +4,9 @@ include(CMake/BuildJsonCpp.cmake)
include(CMake/BuildFmt.cmake)
include(CMake/BuildCppRestSdk.cmake)
include(CMake/BuildAzure.cmake)
include(CMake/BuildCurl.cmake)
include(CMake/BuildLibUV.cmake)
if (BUILD_ZLIB)
include(CMake/BuildZlib.cmake)
endif()
......@@ -18,4 +21,6 @@ macro(build3rdparty)
BuildCppRestSdk()
BuildAzure()
add_subdirectory(${pybind11_SOURCE_DIR} ${PROJECT_BINARY_DIR}/pybind11_${pybind11_VERSION} EXCLUDE_FROM_ALL)
BuildCurl()
BuildLibUV()
endmacro()
function(BuildCurl)
if (NOT BUILD_CURL)
return()
endif()
if (WIN32)
list(APPEND CURL_LIBS_LIST_RELEASE "lib/libcurl_imp.lib")
list(APPEND CURL_DLLS_LIST_RELEASE "bin/libcurl.dll")
list(APPEND CURL_LIBS_LIST_DEBUG "lib/libcurl-d_imp.lib")
list(APPEND CURL_DLLS_LIST_DEBUG "bin/libcurl-d.dll")
endif()
BuildExternal(curl ${curl_VERSION} "" ${curl_SOURCE_DIR} "${CURL_LIBS_LIST_RELEASE}" "${CURL_DLLS_LIST_RELEASE}" "${CURL_LIBS_LIST_DEBUG}" "${CURL_DLLS_LIST_DEBUG}" "-DBUILD_CURL_EXE=OFF;-DHTTP_ONLY=ON;-DBUILD_TESTING=OFF;-DCMAKE_USE_WINSSL=ON")
endfunction()
function(BuildLibUV)
if (NOT BUILD_UV)
return()
endif()
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (${isMultiConfig}) ##we don't need build byproducts for visual studio or xcode
set(LIB_PREFIX "lib/$<CONFIG>")
else()
set(LIB_PREFIX "lib/${CMAKE_BUILD_TYPE}")
endif()
if (WIN32)
list(APPEND LIBUV_LIBS_LIST "${LIB_PREFIX}/uv.lib")
list(APPEND LIBUV_DLLS_LIST "${LIB_PREFIX}/uv.dll")
endif()
BuildExternal(libuv ${libuv_VERSION} "" ${libuv_SOURCE_DIR} "${LIBUV_LIBS_LIST}" "${LIBUV_DLLS_LIST}" "" "" "")
endfunction()
......@@ -29,6 +29,8 @@ function(Fetch3rdParty)
Fetch3rdParty_Package(cpprestapi 2.10.14 https://github.com/microsoft/cpprestsdk/archive/v2.10.14.tar.gz SHA256=f2628b248f714d7bbd6a536553bc3782602c68ca1b129017985dd70cc3515278)
Fetch3rdParty_Package(azure-storage-cpp 7.0.0 https://github.com/Azure/azure-storage-cpp/archive/v7.0.0.tar.gz SHA256=2129511dcf40383de5ac643abf68cad4907b5cdbfe471c75ba264a83e3078dc7)
Fetch3rdParty_Package(pybind11 2.4.3 https://github.com/pybind/pybind11/archive/v2.4.3.tar.gz SHA256=1eed57bc6863190e35637290f97a20c81cfe4d9090ac0a24f3bbf08f265eb71d)
Fetch3rdParty_Package(curl 7.68.0 https://github.com/curl/curl/releases/download/curl-7_68_0/curl-7.68.0.tar.gz SHA256=1dd7604e418b0b9a9077f62f763f6684c1b092a7bc17e3f354b8ad5c964d7358)
Fetch3rdParty_Package(libuv 1.34.1 https://github.com/libuv/libuv/archive/v1.34.1.tar.gz SHA256=e3e0105c9b26e181e0547607cb6893462beb0c652674c3795766b2e5555288b3)
if (BUILD_ZLIB)
Fetch3rdParty_Package(zlib 1.2.11 http://zlib.net/zlib-1.2.11.tar.gz SHA256=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1)
......
#[=======================================================================[.rst:
FindLibUV
---------
Find libuv includes and library.
Imported Targets
^^^^^^^^^^^^^^^^
An :ref:`imported target <Imported targets>` named
``LibUV::LibUV`` is provided if libuv has been found.
Result Variables
^^^^^^^^^^^^^^^^
This module defines the following variables:
``LibUV_FOUND``
True if libuv was found, false otherwise.
``LibUV_INCLUDE_DIRS``
Include directories needed to include libuv headers.
``LibUV_LIBRARIES``
Libraries needed to link to libuv.
``LibUV_VERSION``
The version of libuv found.
``LibUV_VERSION_MAJOR``
The major version of libuv.
``LibUV_VERSION_MINOR``
The minor version of libuv.
``LibUV_VERSION_PATCH``
The patch version of libuv.
Cache Variables
^^^^^^^^^^^^^^^
This module uses the following cache variables:
``LibUV_LIBRARY``
The location of the libuv library file.
``LibUV_INCLUDE_DIR``
The location of the libuv include directory containing ``uv.h``.
The cache variables should not be used by project code.
They may be set by end users to point at libuv components.
#]=======================================================================]
#=============================================================================
# Copyright 2014-2016 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
#-----------------------------------------------------------------------------
find_library(LibUV_LIBRARY
NAMES uv
)
mark_as_advanced(LibUV_LIBRARY)
find_path(LibUV_INCLUDE_DIR
NAMES uv.h
)
mark_as_advanced(LibUV_INCLUDE_DIR)
#-----------------------------------------------------------------------------
# Extract version number if possible.
set(_LibUV_H_REGEX "#[ \t]*define[ \t]+UV_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+")
if(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv-version.h")
file(STRINGS "${LibUV_INCLUDE_DIR}/uv-version.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
elseif(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv.h")
file(STRINGS "${LibUV_INCLUDE_DIR}/uv.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
else()
set(_LibUV_H "")
endif()
foreach(c MAJOR MINOR PATCH)
if(_LibUV_H MATCHES "#[ \t]*define[ \t]+UV_VERSION_${c}[ \t]+([0-9]+)")
set(_LibUV_VERSION_${c} "${CMAKE_MATCH_1}")
else()
unset(_LibUV_VERSION_${c})
endif()
endforeach()
if(DEFINED _LibUV_VERSION_MAJOR AND DEFINED _LibUV_VERSION_MINOR)
set(LibUV_VERSION_MAJOR "${_LibUV_VERSION_MAJOR}")
set(LibUV_VERSION_MINOR "${_LibUV_VERSION_MINOR}")
set(LibUV_VERSION "${LibUV_VERSION_MAJOR}.${LibUV_VERSION_MINOR}")
if(DEFINED _LibUV_VERSION_PATCH)
set(LibUV_VERSION_PATCH "${_LibUV_VERSION_PATCH}")
set(LibUV_VERSION "${LibUV_VERSION}.${LibUV_VERSION_PATCH}")
else()
unset(LibUV_VERSION_PATCH)
endif()
else()
set(LibUV_VERSION_MAJOR "")
set(LibUV_VERSION_MINOR "")
set(LibUV_VERSION_PATCH "")
set(LibUV_VERSION "")
endif()
unset(_LibUV_VERSION_MAJOR)
unset(_LibUV_VERSION_MINOR)
unset(_LibUV_VERSION_PATCH)
unset(_LibUV_H_REGEX)
unset(_LibUV_H)
#-----------------------------------------------------------------------------
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUV
FOUND_VAR LibUV_FOUND
REQUIRED_VARS LibUV_LIBRARY LibUV_INCLUDE_DIR
VERSION_VAR LibUV_VERSION
)
set(LIBUV_FOUND ${LibUV_FOUND})
#-----------------------------------------------------------------------------
# Provide documented result variables and targets.
if(LibUV_FOUND)
set(LibUV_INCLUDE_DIRS ${LibUV_INCLUDE_DIR})
set(LibUV_LIBRARIES ${LibUV_LIBRARY})
if(NOT TARGET LibUV::LibUV)
add_library(LibUV::LibUV UNKNOWN IMPORTED)
set_target_properties(LibUV::LibUV PROPERTIES
IMPORTED_LOCATION "${LibUV_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${LibUV_INCLUDE_DIRS}"
)
endif()
endif()
......@@ -81,11 +81,17 @@ endif()
if (WIN32)
set(DEFAULT_BUILD_ZLIB ON)
set(DEFAULT_BUILD_CURL ON)
set(DEFAULT_BUILD_UV ON)
else()
set(DEFAULT_BUILD_ZLIB OFF)
set(DEFAULT_BUILD_CURL OFF)
set(DEFAULT_BUILD_UV OFF)
endif()
option(BUILD_ZLIB "Build zlib" ${DEFAULT_BUILD_ZLIB})
option(BUILD_CURL "Build libcurl as part of the openVDS build" ${DEFAULT_BUILD_CURL})
option(BUILD_UV "Build libuv as part of the openVDS build" ${DEFAULT_BUILD_UV})
include(CMake/Fetch3rdPartyInBuild.cmake)
Fetch3rdParty()
......
......@@ -2,7 +2,7 @@ FROM alpine:latest
# Install the various required packages
RUN apk add python3 python3-dev gcc g++ cmake make git \
libxml2-dev boost-dev zlib-dev openssl-dev curl-dev \
libxml2-dev boost-dev zlib-dev openssl-dev curl-dev libuv-dev \
util-linux-dev # This package contains the uuid development headers
# Copy the python requirement list into the container and download the packages
......
......@@ -76,6 +76,8 @@ int main(int argc, char **argv)
std::string container;
int azureParallelismFactor = 0;
std::string object;
std::string azurePresignBase;
std::string azurePresignSuffix;
std::string axis = "0,1,2";
int axis_position = std::numeric_limits<int>::min();
int32_t output_width = 500;
......@@ -88,6 +90,8 @@ int main(int argc, char **argv)
options.add_option("", "", "container", "Azure Blob Storage container to download from .", cxxopts::value<std::string>(container), "<string>");
options.add_option("", "", "parallelism-factor", "Azure parallelism factor.", cxxopts::value<int>(azureParallelismFactor), "<value>");
options.add_option("", "", "object", "ObjectId of the VDS", cxxopts::value(object), "<string>");
options.add_option("", "", "azure-presign-base", "Base URL for presigned Azure requests", cxxopts::value(azurePresignBase), "<value>");
options.add_option("", "", "azure-presign-suffix", "Suffix of the presigned URL for Azure requests", cxxopts::value(azurePresignSuffix), "<value>");
options.add_option("", "", "axis", "Axis mapping. Comma seperated list. First digite is the axis for the slice. "
"Second is the x axis and third is the y axis", cxxopts::value(axis), "<axis id>");
options.add_option("", "", "noise", "Generate a noise VDS in memory, and grab a slice from this (default off).", cxxopts::value(generate_noise), "<enable>");
......@@ -107,7 +111,7 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
if (bucket.empty() && container.empty() && !generate_noise)
if (bucket.empty() && container.empty() && !generate_noise && azurePresignBase.empty())
{
fmt::print(stderr, "Either an Azure Blob Storage container name or an AWS S3 bucket name must be specified");
return EXIT_FAILURE;
......@@ -165,6 +169,14 @@ int main(int argc, char **argv)
handle = OpenVDS::Open(openOptions, error);
}
else if (!azurePresignBase.empty())
{
OpenVDS::AzurePresignedOpenOptions openOptions;
openOptions.baseUrl = azurePresignBase;
openOptions.urlSuffix = azurePresignSuffix;
handle = OpenVDS::Open(openOptions, error);
}
if (!handle)
{
......
......@@ -7,6 +7,8 @@ set(SOURCE_FILES
IO/IOManagerAWS.cpp
IO/IOManagerAzure.cpp
IO/IOManagerInMemory.cpp
IO/IOManagerCurl.cpp
IO/IOManagerAzurePresigned.cpp
VDS/VolumeDataPartition.cpp
VDS/VolumeDataChannelMapping.cpp
VDS/VolumeDataLayer.cpp
......@@ -40,6 +42,8 @@ set (PRIVATE_HEADER_FILES
IO/IOManagerAWS.h
IO/IOManagerAzure.h
IO/IOManagerInMemory.h
IO/IOManagerCurl.h
IO/IOManagerAzurePresigned.h
VDS/VDS.h
VDS/VolumeDataPartition.h
VDS/VolumeDataChannelMapping.h
......@@ -161,6 +165,16 @@ else()
target_link_libraries(openvds_objects PUBLIC ZLIB::ZLIB)
endif()
if (NOT BUILD_CURL)
find_package(CURL REQUIRED)
target_link_libraries(openvds_objects PUBLIC ${CURL_LIBRARIES})
target_include_directories(openvds_objects PUBLIC ${CURL_INCLUDE_DIRS})
endif()
if (NOT BUILD_UV)
find_package(LibUV REQUIRED)
target_link_libraries(openvds_objects PUBLIC LibUV::LibUV)
endif()
if (WIN32)
set_source_files_properties(IO/Linux_File.cpp PROPERTIES HEADER_FILE_ONLY TRUE)
elseif (UNIX)
......
......@@ -21,6 +21,7 @@
#include "IOManagerAWS.h"
#include "IOManagerAzure.h"
#include "IOManagerInMemory.h"
#include "IOManagerAzurePresigned.h"
namespace OpenVDS
{
......@@ -41,6 +42,8 @@ IOManager* IOManager::CreateIOManager(const OpenOptions& options, Error &error)
return new IOManagerAWS(static_cast<const AWSOpenOptions &>(options), error);
case OpenOptions::Azure:
return new IOManagerAzure(static_cast<const AzureOpenOptions&>(options), error);
case OpenOptions::AzurePresigned:
return new IOManagerAzurePresigned(static_cast<const AzurePresignedOpenOptions&>(options).baseUrl, static_cast<const AzurePresignedOpenOptions&>(options).urlSuffix, error);
case OpenOptions::InMemory:
return new IOManagerInMemory(static_cast<const InMemoryOpenOptions &>(options), error);
default:
......
/****************************************************************************
** Copyright 2020 The Open Group
** Copyright 2020 Bluware, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
****************************************************************************/
#include "IOManagerAzurePresigned.h"
#include <fmt/format.h>
namespace OpenVDS
{
IOManagerAzurePresigned::IOManagerAzurePresigned(const std::string& base, const std::string& suffix, Error &error)
: m_curlHandler(error)
, m_base(base)
, m_suffix(suffix)
{
if (m_base.empty())
{
error.code = -1;
error.string = "IOManagerPresigned: empty base url";
return;
}
if (m_base.back() != '/')
m_base.push_back('/');
}
std::shared_ptr<Request> IOManagerAzurePresigned::ReadObjectInfo(const std::string& objectName, std::shared_ptr<TransferDownloadHandler> handler)
{
std::string url = m_base + objectName + m_suffix;
std::shared_ptr<DownloadRequestCurl> request = std::make_shared<DownloadRequestCurl>(objectName, handler);
std::vector<std::string> headers;
m_curlHandler.addDownloadRequest(request, url, headers, "x-ms-meta-", CurlDownloadHandler::HEADER);
return request;
}
std::shared_ptr<Request> IOManagerAzurePresigned::ReadObject(const std::string& objectName, std::shared_ptr<TransferDownloadHandler> handler, const IORange& range)
{
std::string url = m_base + objectName + m_suffix;
std::shared_ptr<DownloadRequestCurl> request = std::make_shared<DownloadRequestCurl>(objectName, handler);
std::vector<std::string> headers;
if (range.start != range.end)
{
headers.emplace_back();
auto& header = headers.back();
header = fmt::format("Range: {}-{}", range.start, range.end);
}
m_curlHandler.addDownloadRequest(request, url, headers, "x-ms-meta-", CurlDownloadHandler::GET);
return request;
}
std::shared_ptr<Request> IOManagerAzurePresigned::WriteObject(const std::string& objectName, const std::string& contentDispostionFilename, const std::string& contentType, const std::vector<std::pair<std::string, std::string>>& metadataHeader, std::shared_ptr<std::vector<uint8_t>> data, std::function<void(const Request& request, const Error& error)> completedCallback)
{
std::string url = m_base + objectName + m_suffix;
std::shared_ptr<UploadRequestCurl> request = std::make_shared<UploadRequestCurl>(objectName, completedCallback);
std::vector<std::string> headers;
headers.emplace_back("x-ms-blob-type: BlockBlob");
if (contentDispostionFilename.size())
headers.push_back(fmt::format("content-disposition: attachment; filename=\"{}\"", contentDispostionFilename));
if (contentType.size())
headers.push_back(fmt::format("content-type: {}", contentType));
if (data->size())
headers.push_back(fmt::format("content-length: {}", data->size()));
for (auto metaTag : metadataHeader)
{
headers.push_back(fmt::format("{}{}: {}", "x-ms-meta-", metaTag.first, metaTag.second));
}
m_curlHandler.addUploadRequest(request, url, headers, data);
return request;
}
}
\ No newline at end of file
/****************************************************************************
** Copyright 2020 The Open Group
** Copyright 2020 Bluware, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
****************************************************************************/
#ifndef IOMANAGERAZUREPRESIGNED_H
#define IOMANAGERAZUREPRESIGNED_H
#include "IOManagerCurl.h"
namespace OpenVDS
{
class IOManagerAzurePresigned : public IOManager
{
public:
IOManagerAzurePresigned(const std::string& base, const std::string& suffix, Error& error);
std::shared_ptr<Request> ReadObjectInfo(const std::string& objectName, std::shared_ptr<TransferDownloadHandler> handler) override;
std::shared_ptr<Request> ReadObject(const std::string& objectName, std::shared_ptr<TransferDownloadHandler> handler, const IORange& range = IORange()) override;
std::shared_ptr<Request> WriteObject(const std::string& objectName, const std::string& contentDispostionFilename, const std::string& contentType, const std::vector<std::pair<std::string, std::string>>& metadataHeader, std::shared_ptr<std::vector<uint8_t>> data, std::function<void(const Request& request, const Error& error)> completedCallback = nullptr) override;
private:
CurlHandler m_curlHandler;
std::string m_base;
std::string m_suffix;
};
}
#endif
This diff is collapsed.
/****************************************************************************
** Copyright 2020 The Open Group
** Copyright 2020 Bluware, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
****************************************************************************/
#ifndef IOMANAGERCURL_H
#define IOMANAGERCURL_H
#include "IOManager.h"
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <atomic>
#include <deque>
#include <condition_variable>
#undef WIN32_LEAN_AND_MEAN // avoid warnings if defined on command line
#define WIN32_LEAN_AND_MEAN
#undef NOMINMAX
#define NOMINMAX 1
#include <uv.h>
#include <curl/curl.h>
#include <fmt/format.h>
namespace OpenVDS
{
static std::string trimInBothEnds(const std::string& str)
{
auto it_begin = std::find_if(str.begin(), str.end(), [](const char a) { return !std::isspace(a); });
auto it_end = std::find_if(str.rbegin(), str.rend(), [](const char a) { return !std::isspace(a); }).base();
if (it_end < it_begin)
return std::string();
return std::string(it_begin, it_end);
}
static void getKeyValueFromLine(const char *line, size_t size, std::string &key, std::string &value, char delimiter)
{
const char *end = line + size;
const char *colon = std::find(line, end, delimiter);
if (colon >= end - 1 )
return;
std::string k(line, colon);
std::string v(colon + 1, end);
key = trimInBothEnds(k);
value = trimInBothEnds(v);
}
class IOManagerCurl;
struct UVEventLoopData;
struct CurlEasyHandler
{
CurlEasyHandler(UVEventLoopData *eventLoopData)
: eventLoopData(eventLoopData)
, curlEasy(nullptr)
{}
UVEventLoopData *eventLoopData;
CURL* curlEasy;
virtual void handleDone(int responsCode, const Error &error) = 0;
virtual bool shouldRetry(int responseCode) { return false; }
virtual void handleHeaderData(char* buffer, size_t size) = 0;
virtual void handleWriteData(char* ptr, size_t size) = 0;
virtual size_t handleReadRequest(char* buffer, size_t size) = 0;
};
struct SocketContext
{
SocketContext(CurlEasyHandler *request, curl_socket_t socket);
CURLM *curlMulti;
curl_socket_t socket;
uv_poll_t pollHandle;
};
struct CurlDownloadHandler;
class DownloadRequestCurl : public Request
{
public:
DownloadRequestCurl(const std::string& id, const std::shared_ptr<TransferDownloadHandler> &handler);
~DownloadRequestCurl() override;
void WaitForFinish() override;
bool IsDone() const override;
bool IsSuccess(Error& error) const override;
void Cancel() override;
std::shared_ptr<CurlDownloadHandler> m_downloadHandler;
std::string m_requestName;
std::shared_ptr<TransferDownloadHandler> m_handler;
bool m_cancelled;
bool m_done;
Error m_error;
std::condition_variable m_waitForFinish;
mutable std::mutex m_mutex;
};
struct CurlDownloadHandler : public CurlEasyHandler
{
enum Verb
{
HEADER,
GET
};
CurlDownloadHandler(UVEventLoopData *eventLoopData, const std::shared_ptr<DownloadRequestCurl> &request, std::string url, std::vector<std::string> headers, std::string metaKeyPrefixTrim, Verb verb)
: CurlEasyHandler(eventLoopData)
, request(request)
, url(std::move(url))
, headers(std::move(headers))
, data(std::move(data))
, metaKeyPrefixTrim(std::move(metaKeyPrefixTrim))
, verb(verb)
{
}
void handleDone(int responsCode, const Error &error) override;
void handleHeaderData(char* buffer, size_t size) override;
void handleWriteData(char* ptr, size_t size) override;
size_t handleReadRequest(char* buffer, size_t size) override;
std::weak_ptr<DownloadRequestCurl> request;
std::string url;
std::vector<std::string> headers;
std::vector<uint8_t> data;
std::string metaKeyPrefixTrim;
Verb verb;
};
struct CurlUploadHandler;
class UploadRequestCurl : public Request
{
public: