19#include "AUI/IO/AEOFException.h"
20#include "AUI/IO/IInputStream.h"
21#include "AUI/Traits/values.h"
22#include "AFormMultipart.h"
23#include <AUI/IO/APipe.h>
24#include <AUI/Common/AByteBufferView.h>
25#include <AUI/Common/AByteBuffer.h>
26#include <AUI/Common/ASignal.h>
27#include <AUI/Reflect/AEnumerate.h>
28#include <AUI/Thread/AFuture.h>
41class API_AUI_CURL ACurl:
public AObject {
42friend class ACurlMulti;
52 VERSION_2_PRIOR_KNOWLEDGE,
59 enum class ResponseCode {
60 HTTP_100_CONTINUE = 100,
61 HTTP_101_SWITCHING_PROTOCOL = 101,
62 HTTP_102_PROCESSING = 102,
63 HTTP_103_EARLY_HINTS = 103,
65 HTTP_201_CREATED = 201,
66 HTTP_202_ACCEPTED = 202,
67 HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203,
68 HTTP_204_NO_CONTENT = 204,
69 HTTP_205_RESET_CONTENT = 205,
70 HTTP_206_PARTIAL_CONTENT = 206,
71 HTTP_300_MULTIPLE_CHOICE = 300,
72 HTTP_301_MOVED_PERMANENTLY = 301,
74 HTTP_303_SEE_OTHER = 303,
75 HTTP_304_NOT_MODIFIED = 304,
76 HTTP_305_USE_PROXY = 305,
77 HTTP_306_SWITCH_PROXY = 306,
78 HTTP_307_TEMPORARY_REDIRECT = 307,
79 HTTP_308_PERMANENT_REDIRECT = 308,
80 HTTP_400_BAD_REQUEST = 400,
81 HTTP_401_UNAUTHORIZED = 401,
82 HTTP_402_PAYMENT_REQUIRED = 402,
83 HTTP_403_FORBIDDEN = 403,
84 HTTP_404_NOT_FOUND = 404,
85 HTTP_405_METHOD_NOT_ALLOWED = 405,
86 HTTP_406_NOT_ACCEPTABLE = 406,
87 HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407,
88 HTTP_408_REQUEST_TIMEOUT = 408,
89 HTTP_409_CONFLICT = 409,
91 HTTP_411_LENGTH_REQUIRED = 411,
92 HTTP_412_PRECONDITION_FAILED = 412,
93 HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413,
94 HTTP_414_REQUEST_URI_TOO_LONG = 414,
95 HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415,
96 HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
97 HTTP_417_EXPECTATION_FAILED = 417,
98 HTTP_500_INTERNAL_SERVER_ERROR = 500,
99 HTTP_501_NOT_IMPLEMENTED = 501,
100 HTTP_502_BAD_GATEWAY = 502,
101 HTTP_503_SERVICE_UNAVAILABLE = 503,
102 HTTP_504_GATEWAY_TIMEOUT = 504,
103 HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505,
129 void throwException()
const;
167 using ReadCallback = std::function<std::size_t(
char* dst,
size_t maxLen)>;
169 using ErrorCallback = std::function<void(
const ErrorDescription& description)>;
172 class Exception:
public AIOException {
174 using AIOException::AIOException;
175 Exception(
const ErrorDescription& errorDescription): AIOException(errorDescription.description),
176 mCurlStatus(errorDescription.curlStatus) {
181 int curlStatus()
const noexcept {
189 class API_AUI_CURL Builder {
195 ErrorCallback mErrorCallback;
196 HeaderCallback mHeaderCallback;
197 bool mThrowExceptionOnError =
false;
200 Method mMethod = Method::HTTP_GET;
201 std::function<void(ACurl&)> mOnSuccess;
205 Builder(
const Builder&) =
delete;
216 return callback(buffer);
227 AUI_ASSERTX(mWriteCallback ==
nullptr,
"write callback already set");
228 mWriteCallback = std::move(callback);
240 mHeaders.push_back(
"Content-Type: multipart/form-data; boundary={}"_format(multipart.boundary()));
250 AUI_ASSERTX(mReadCallback ==
nullptr,
"write callback already set");
251 mReadCallback = std::move(callback);
261 withBody([inputStream = std::move(inputStream)](
char* dst, std::size_t length) {
262 auto v = inputStream->read(dst, length);
281 AUI_ASSERTX(mReadCallback ==
nullptr,
"write callback already set");
284 explicit Body(std::string b) : contents(std::move(b)), i(contents.begin()) {}
286 std::string contents;
287 std::string::iterator i;
289 auto b = _new<Body>(std::move(contents));
291 mReadCallback = [body = std::move(b)](
char* dst, std::size_t length)
mutable {
292 if (body->i == body->contents.end()) {
295 std::size_t remaining = std::distance(body->i, body->contents.end());
296 length = glm::min(length, remaining);
297 std::memcpy(dst, &*body->i, length);
311 mHeaderCallback = std::move(headerCallback);
319 AUI_ASSERTX(mErrorCallback ==
nullptr,
"error callback already set");
320 mErrorCallback = std::move(callback);
331 Builder& withOutputStream(_<IOutputStream> dst) {
332 return withWriteCallback([dst = std::move(dst)](AByteBufferView b) {
338 Builder& throwExceptionOnError(
bool throwExceptionOnError)
noexcept {
339 mThrowExceptionOnError = throwExceptionOnError;
377 Builder& withHttpVersion(Http version);
378 Builder& withUpload(
bool upload);
379 Builder& withCustomRequest(
const AString& v);
380 Builder& withOnSuccess(std::function<
void(ACurl&)> onSuccess) {
381 mOnSuccess = std::move(onSuccess);
385 template<aui::invocable OnSuccess>
386 Builder& withOnSuccess(OnSuccess&& onSuccess) {
387 mOnSuccess = [onSuccess = std::forward<OnSuccess>(onSuccess)](ACurl&) {
422 mParams = std::move(params);
427 mHeaders = std::move(headers);
460 explicit ACurl(
Builder& builder):
461 ACurl(std::move(builder))
465 explicit ACurl(Builder&& builder)
noexcept {
466 operator=(std::move(builder));
468 ACurl(ACurl&& o)
noexcept {
469 operator=(std::move(o));
474 ACurl& operator=(Builder&& o)
noexcept;
475 ACurl& operator=(ACurl&& o)
noexcept;
477 int64_t getContentLength()
const;
478 int64_t getNumberOfBytesDownloaded()
const;
479 AString getContentType()
const;
500 void* handle() const noexcept {
505 ResponseCode getResponseCode()
const;
508 AString getErrorString() const noexcept {
509 return AString::fromLatin1(mErrorBuffer);
514 struct curl_slist* mCurlHeaders =
nullptr;
515 char mErrorBuffer[256];
516 bool mCloseRequested =
false;
517 bool mThrowExceptionOnError =
false;
518 std::string mPostFieldsStorage;
520 static size_t writeCallback(
char* ptr,
size_t size,
size_t nmemb,
void* userdata)
noexcept;
521 static size_t readCallback(
char* ptr,
size_t size,
size_t nmemb,
void* userdata)
noexcept;
522 static size_t headerCallback(
char *buffer,
size_t size,
size_t nitems,
void *userdata)
noexcept;
524 WriteCallbackV2 mWriteCallback;
525 ReadCallback mReadCallback;
526 HeaderCallback mHeaderCallback;
528 void reportSuccess() {
532 void reportFail(
const ErrorDescription& errorDescription) {
533 emit fail(errorDescription);
536 void reportFail(
int statusCode) {
537 reportFail(ErrorDescription{statusCode, AString::fromLatin1(mErrorBuffer)});
540 template<
typename Ret>
541 Ret getInfo(
int curlInfo)
const;
566 ACurl::ResponseCode::HTTP_100_CONTINUE,
567 ACurl::ResponseCode::HTTP_101_SWITCHING_PROTOCOL,
568 ACurl::ResponseCode::HTTP_102_PROCESSING,
569 ACurl::ResponseCode::HTTP_103_EARLY_HINTS,
570 ACurl::ResponseCode::HTTP_200_OK,
571 ACurl::ResponseCode::HTTP_201_CREATED,
572 ACurl::ResponseCode::HTTP_202_ACCEPTED,
573 ACurl::ResponseCode::HTTP_203_NON_AUTHORITATIVE_INFORMATION,
574 ACurl::ResponseCode::HTTP_204_NO_CONTENT,
575 ACurl::ResponseCode::HTTP_205_RESET_CONTENT,
576 ACurl::ResponseCode::HTTP_206_PARTIAL_CONTENT,
577 ACurl::ResponseCode::HTTP_300_MULTIPLE_CHOICE,
578 ACurl::ResponseCode::HTTP_301_MOVED_PERMANENTLY,
579 ACurl::ResponseCode::HTTP_302_FOUND,
580 ACurl::ResponseCode::HTTP_303_SEE_OTHER,
581 ACurl::ResponseCode::HTTP_304_NOT_MODIFIED,
582 ACurl::ResponseCode::HTTP_305_USE_PROXY,
583 ACurl::ResponseCode::HTTP_306_SWITCH_PROXY,
584 ACurl::ResponseCode::HTTP_307_TEMPORARY_REDIRECT,
585 ACurl::ResponseCode::HTTP_308_PERMANENT_REDIRECT,
586 ACurl::ResponseCode::HTTP_400_BAD_REQUEST,
587 ACurl::ResponseCode::HTTP_401_UNAUTHORIZED,
588 ACurl::ResponseCode::HTTP_402_PAYMENT_REQUIRED,
589 ACurl::ResponseCode::HTTP_403_FORBIDDEN,
590 ACurl::ResponseCode::HTTP_404_NOT_FOUND,
591 ACurl::ResponseCode::HTTP_405_METHOD_NOT_ALLOWED,
592 ACurl::ResponseCode::HTTP_406_NOT_ACCEPTABLE,
593 ACurl::ResponseCode::HTTP_407_PROXY_AUTHENTICATION_REQUIRED,
594 ACurl::ResponseCode::HTTP_408_REQUEST_TIMEOUT,
595 ACurl::ResponseCode::HTTP_409_CONFLICT,
596 ACurl::ResponseCode::HTTP_410_GONE,
597 ACurl::ResponseCode::HTTP_411_LENGTH_REQUIRED,
598 ACurl::ResponseCode::HTTP_412_PRECONDITION_FAILED,
599 ACurl::ResponseCode::HTTP_413_REQUEST_ENTITY_TOO_LARGE,
600 ACurl::ResponseCode::HTTP_414_REQUEST_URI_TOO_LONG,
601 ACurl::ResponseCode::HTTP_415_UNSUPPORTED_MEDIA_TYPE,
602 ACurl::ResponseCode::HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE,
603 ACurl::ResponseCode::HTTP_417_EXPECTATION_FAILED,
604 ACurl::ResponseCode::HTTP_500_INTERNAL_SERVER_ERROR,
605 ACurl::ResponseCode::HTTP_501_NOT_IMPLEMENTED,
606 ACurl::ResponseCode::HTTP_502_BAD_GATEWAY,
607 ACurl::ResponseCode::HTTP_503_SERVICE_UNAVAILABLE,
608 ACurl::ResponseCode::HTTP_504_GATEWAY_TIMEOUT,
609 ACurl::ResponseCode::HTTP_505_HTTP_VERSION_NOT_SUPPORTED)
Acts like std::string_view but for AByteBuffer.
Definition AByteBufferView.h:24
std::vector-like growing array for byte storage.
Definition AByteBuffer.h:31
Multi curl instance.
Definition ACurlMulti.h:44
Builder & withMultipart(const AFormMultipart &multipart)
Add multipart data.
Definition ACurl.h:238
Builder & withTimeout(std::chrono::seconds timeout)
Specifies acceptable response time.
Builder & withBody(std::string contents)
Like withBody with callback, but wrapped with string.
Definition ACurl.h:280
AFuture< Response > runAsync(ACurlMulti &curlMulti)
Constructs ACurl object and performs curl request in specified ACurlMulti.
_unique< IInputStream > toInputStream()
Makes input stream from curl builder.
Builder & withLowSpeedTime(std::chrono::seconds duration)
Duration that the transfer speed should be below the 'low speed limit' to consider it to be too slow ...
Builder & withLowSpeedLimit(size_t speed)
Set the average transfer speed in bytes per that the transfer should be below during 'low speed time'...
Builder & withRanges(size_t begin, size_t end)
Sets: Accept-Ranges: begin-end (download part of the file)
Builder & withWriteCallback(WriteCallback callback)
Called on server -> client data received (download).
Definition ACurl.h:214
Response runBlocking()
Constructs ACurl object and performs curl request in blocking mode. Use toFuture() instead if possibl...
Builder & withParams(AString params) noexcept
Sets HTTP params to the query.
Definition ACurl.h:421
Builder & withErrorCallback(ErrorCallback callback)
Definition ACurl.h:318
Builder & withHeaderCallback(HeaderCallback headerCallback)
Called on header received.
Definition ACurl.h:310
Builder & withParams(const AVector< std::pair< AString, AString > > ¶ms)
Sets HTTP params to the query.
Builder & withInputStream(_< IInputStream > inputStream)
Called on client -> server data requested (upload).
Definition ACurl.h:260
Builder & withBody(ReadCallback callback)
Called on client -> server data requested (upload).
Definition ACurl.h:249
AFuture< Response > runAsync()
Constructs ACurl object and performs curl request in global ACurlMulti.
Builder & withMethod(Method method) noexcept
Sets HTTP method to the query.
Definition ACurl.h:398
Builder & withRanges(size_t begin)
Sets: Accept-Ranges: begin-end (download part of the file)
Definition ACurl.h:358
Builder & withWriteCallback(WriteCallbackV2 callback)
Called on server -> client data received (download).
Definition ACurl.h:226
Easy curl instance.
Definition ACurl.h:41
virtual void close()
Breaks curl loop in the run() method, closing underlying curl connection.
std::function< size_t(ACurl &curl, AByteBufferView data)> WriteCallbackV2
A read callback.
Definition ACurl.h:155
std::function< size_t(AByteBufferView data)> WriteCallback
A read callback.
Definition ACurl.h:142
emits success
Emitted on success.
Definition ACurl.h:558
emits< ErrorDescription > fail
Emitted on network error.
Definition ACurl.h:551
std::function< std::size_t(char *dst, size_t maxLen)> ReadCallback
A read callback.
Definition ACurl.h:167
Thrown when stream has reached end (end of file).
Definition AEOFException.h:20
Represents a value that will be available at some point in the future.
Definition AFuture.h:621
Represents a Unicode character string.
Definition AString.h:38
A std::vector with AUI extensions.
Definition AVector.h:39
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
Avoids copy of the wrapped value, pointing to a reference.
Definition values.h:361
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:572
#define emit
emits the specified signal in context of this object.
Definition AObject.h:343
#define AUI_ENUM_VALUES(enum_t,...)
Defines all enum values for AEnumerate.
Definition AEnumerate.h:208
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74
Response struct for Builder::runBlocking() and Builder::runAsync()
Definition ACurl.h:118