5#include "../Common/CompilerMacrosExport.h"
6#include "../Common/CompilerMacrosType.h"
7#ifndef SC_EXPORT_LIBRARY_HTTP_CLIENT
8#define SC_EXPORT_LIBRARY_HTTP_CLIENT 0
10#define SC_HTTP_CLIENT_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_HTTP_CLIENT)
12#include "../Common/Result.h"
13#include "../Common/Span.h"
14#include "../Common/StringSpan.h"
15#include "Internal/HttpClientThreading.h"
22struct SC_HTTP_CLIENT_EXPORT HttpClientRequestBodyProvider;
23struct SC_HTTP_CLIENT_EXPORT HttpClientRequestOptions;
54 [[nodiscard]]
bool isIdentity()
const {
return type == Identity; }
55 [[nodiscard]]
static Type parseName(StringSpan name);
56 [[nodiscard]]
static const char* getName(Type type);
57 [[nodiscard]]
static Result writeAcceptEncoding(Span<const Type> types, Span<char> destination, StringSpan& value);
64 StringSpan headerValue;
65 size_t valueOffset = 0;
66 bool hasHeaderValue =
false;
84 [[nodiscard]]
bool isChunked()
const {
return type == Chunked; }
85 [[nodiscard]]
static Type parseName(StringSpan name);
86 [[nodiscard]]
static const char* getName(Type type);
93 StringSpan headerValue;
94 size_t valueOffset = 0;
95 bool hasHeaderValue =
false;
101 enum Backend : uint8_t
109 enum Feature : uint8_t
111 MultipleOperationsPerClient,
113 SizedStreamRequestBody,
114 ChunkedStreamRequestBody,
117 ProtocolHttp2Preferred,
118 ProtocolHttp2Required,
119 TlsDisablePeerVerification,
128 Backend backend = Unsupported;
130 bool multipleOperationsPerClient =
false;
131 bool fixedRequestBody =
false;
132 bool sizedStreamRequestBody =
false;
133 bool chunkedStreamRequestBody =
false;
134 bool redirectPolicy =
false;
135 bool protocolHttp11Only =
false;
136 bool protocolHttp2Preferred =
false;
137 bool protocolHttp2Required =
false;
138 bool tlsDisablePeerVerification =
false;
139 bool tlsCustomCaPath =
false;
140 bool proxyNoProxy =
false;
141 bool proxyHttp =
false;
142 bool proxyAuthorization =
false;
143 bool proxyBypassList =
false;
144 bool contentCodingPolicy =
false;
146 [[nodiscard]]
bool hasBackend(Backend requiredBackend)
const;
147 [[nodiscard]]
bool supports(Feature feature)
const;
149 [[nodiscard]]
bool supportsAll(Span<const Feature> features)
const;
150 [[nodiscard]] Result requireBackend(Backend requiredBackend)
const;
151 [[nodiscard]] Result requireFeatures(Span<const Feature> features)
const;
153 [[nodiscard]]
const char* getBackendName()
const;
154 [[nodiscard]]
static const char* getBackendName(Backend backend);
155 [[nodiscard]]
static const char* getFeatureName(Feature feature);
172 Span<const char> bytes;
175 uint64_t sizeInBytes = 0;
176 bool canReplay =
false;
180 [[nodiscard]]
bool isStreamed()
const {
return framing == SizedStream or framing == ChunkedStream; }
181 [[nodiscard]]
bool isChunkedStream()
const {
return framing == ChunkedStream; }
182 [[nodiscard]]
const char* getFramingName()
const {
return getFramingName(framing); }
183 [[nodiscard]]
static const char* getFramingName(Framing framing);
184 [[nodiscard]] uint64_t getDeclaredSizeInBytes()
const
186 if (framing == FixedSize)
188 return static_cast<uint64_t
>(bytes.sizeInBytes());
190 return framing == SizedStream ? sizeInBytes : 0;
204 Mode mode = NoRedirects;
205 uint8_t maxRedirects = 10;
207 [[nodiscard]]
const char* getModeName()
const {
return getModeName(mode); }
208 [[nodiscard]]
static const char* getModeName(Mode mode);
214 uint32_t requestTimeoutMs = 30000;
220 bool verifyPeer =
true;
221 StringSpan caCertificatesPath;
227 enum Preference : uint8_t
235 Preference preference = Default;
237 [[nodiscard]]
const char* getPreferenceName()
const {
return getPreferenceName(preference); }
238 [[nodiscard]]
static const char* getPreferenceName(Preference preference);
256 [[nodiscard]]
const char* getModeName()
const {
return getModeName(mode); }
257 [[nodiscard]]
static const char* getModeName(Mode mode);
276 enum Method : uint8_t
287 Method method = HttpGET;
291 Span<const HttpClientHeader> headers;
295 [[nodiscard]]
const char* getMethodName()
const {
return getMethodName(method); }
296 [[nodiscard]]
static const char* getMethodName(Method method);
297 [[nodiscard]] Result validate()
const;
305 enum class Protocol : uint8_t
314 Span<const char> headers;
316 size_t headersLength = 0;
317 Protocol negotiatedProtocol = Protocol::Unknown;
318 StringSpan effectiveUrl;
319 uint32_t redirectCount = 0;
321 [[nodiscard]]
bool getHeader(StringSpan name, StringSpan& value)
const;
322 [[nodiscard]]
bool hasHeader(StringSpan name)
const;
324 StringSpan& value)
const;
326 [[nodiscard]]
bool getContentLength(uint64_t& value)
const;
327 [[nodiscard]]
bool getContentType(StringSpan& value)
const;
328 [[nodiscard]]
bool getContentEncoding(StringSpan& value)
const;
329 [[nodiscard]]
bool getTransferEncoding(StringSpan& value)
const;
330 [[nodiscard]]
bool getLocation(StringSpan& value)
const;
331 [[nodiscard]]
bool getWwwAuthenticate(StringSpan& value)
const;
332 [[nodiscard]]
bool getProxyAuthenticate(StringSpan& value)
const;
337 [[nodiscard]]
bool hasContentCoding(HttpClientContentCoding::Type type)
const;
338 [[nodiscard]]
bool hasTransferCoding(HttpClientTransferCoding::Type type)
const;
339 [[nodiscard]]
bool isHttp11()
const {
return negotiatedProtocol == Protocol::Http11; }
340 [[nodiscard]]
bool isHttp2()
const {
return negotiatedProtocol == Protocol::Http2; }
341 [[nodiscard]]
bool isInformationalStatus()
const {
return statusCode >= 100 and statusCode < 200; }
342 [[nodiscard]]
bool isSuccessfulStatus()
const {
return statusCode >= 200 and statusCode < 300; }
343 [[nodiscard]]
bool isRedirectStatus()
const {
return statusCode >= 300 and statusCode < 400; }
344 [[nodiscard]]
bool isClientErrorStatus()
const {
return statusCode >= 400 and statusCode < 500; }
345 [[nodiscard]]
bool isServerErrorStatus()
const {
return statusCode >= 500 and statusCode < 600; }
346 [[nodiscard]]
bool isErrorStatus()
const {
return statusCode >= 400; }
347 [[nodiscard]]
const char* getProtocolName()
const {
return getProtocolName(negotiatedProtocol); }
348 [[nodiscard]]
static const char* getProtocolName(Protocol protocol);
361 virtual Result
pullRequestBody(Span<char> dest,
size_t& bytesWritten,
bool& endReached) = 0;
382 virtual void onError(Result error) { (void)(error); }
385struct SC_HTTP_CLIENT_EXPORT HttpClientOperation;
410 enum class Type : uint8_t
418 Type type = Type::ResponseHead;
420 size_t bufferIndex = 0;
421 Result error = Result(
true);
433 Span<HttpClientResponseBuffer> responseBuffers;
434 Span<HttpClientOperationEvent> eventQueue;
437 Span<char> responseHeaders;
438 Span<char> responseMetadata;
439 Span<char> backendScratch;
445#pragma warning(disable : 4324)
457 [[nodiscard]] Result init();
458 [[nodiscard]] Result init(HttpClientCapabilities::Backend requiredBackend);
459 [[nodiscard]] Result init(Span<const HttpClientCapabilities::Feature> requiredFeatures);
460 [[nodiscard]] Result init(HttpClientCapabilities::Backend requiredBackend,
461 Span<const HttpClientCapabilities::Feature> requiredFeatures);
462 [[nodiscard]] Result close();
465 [[nodiscard]]
bool isInitialized()
const {
return initialized; }
475 Span<char> bodyBuffer,
size_t& bodyLength,
481 friend struct Internal;
482 friend struct HttpClientLinuxCallbacks;
485 Result platformInit();
486 Result platformClose();
488 bool initialized =
false;
491 alignas(uint64_t)
char storage[128];
492#elif SC_PLATFORM_WINDOWS
493 alignas(uint64_t)
char storage[128];
494#elif SC_PLATFORM_LINUX
495 alignas(uint64_t)
char storage[512];
497 alignas(uint64_t)
char storage[8];
513 [[nodiscard]] Result close();
514 [[nodiscard]] Result cancel();
527 [[nodiscard]] Result
poll(uint32_t timeoutMilliseconds = 0);
533 [[nodiscard]]
bool isInitialized()
const {
return initialized; }
534 [[nodiscard]]
bool isRequestInFlight()
const {
return requestInFlight; }
536 friend struct Internal;
540 friend struct HttpClientAppleCallbacks;
541 friend struct HttpClientLinuxCallbacks;
542 friend struct HttpClientWindowsCallbacks;
544 Result platformInit();
545 Result platformClose();
546 Result platformStart();
547 Result platformCancel();
549 Result enqueueEvent(
const HttpClientOperationEvent& event);
550 bool dequeueEvent(HttpClientOperationEvent& event);
552 Result allocateResponseBuffer(
size_t minimumSizeInBytes,
size_t& bufferIndex, Span<char>& data);
553 void releaseResponseBuffer(
size_t bufferIndex);
554 Result enqueueResponseDataCopy(Span<const char> data);
556 void enqueueResponseHead();
557 void enqueueResponseBuffer(
size_t bufferIndex,
size_t size);
558 void enqueueResponseComplete();
559 void enqueueError(Result error);
561 void resetResponseState(HttpClientResponse& response);
562 void resetRequestBodyState();
563 bool isAutomaticRedirectEnabled()
const;
564 bool canAutomaticRedirectRequestReplay()
const;
565 Result copyResponseEffectiveUrl(StringSpan url);
567 size_t readRequestBodyChunk(Span<char> dest, Result& outError,
bool& outEnd);
568 bool hasPendingEvents()
const;
569 Result processPendingEvents();
571 HttpClient* client =
nullptr;
572 HttpClientResponse* currentResponse =
nullptr;
573 HttpClientOperationListener* currentListener =
nullptr;
574 HttpClientOperationNotifier* notifier =
nullptr;
575 HttpClientRequest currentRequest;
577 Span<HttpClientResponseBuffer> responseBuffers;
578 Span<HttpClientOperationEvent> eventQueue;
580 Span<char> responseHeaders;
581 Span<char> responseMetadata;
582 Span<char> backendScratch;
584 mutable HttpClientLocalMutex eventMutex;
585 HttpClientLocalConditionVariable eventCV;
586 HttpClientOperationEvent dequeuedEvent;
588 size_t eventHead = 0;
589 size_t eventTail = 0;
590 size_t eventCount = 0;
591 bool requestBodyFinished =
false;
592 Result requestBodyError = Result(
true);
593 uint64_t requestBodyBytesRead = 0;
594 bool initialized =
false;
595 bool requestInFlight =
false;
598 alignas(uint64_t)
char storage[512];
599#elif SC_PLATFORM_WINDOWS
600 alignas(uint64_t)
char storage[256];
601#elif SC_PLATFORM_LINUX
602 alignas(uint64_t)
char storage[512];
604 alignas(uint64_t)
char storage[8];
Compile-time backend capability report for the active HttpClient backend.
Definition HttpClient.h:100
Caller-owned cursor for iterating comma-separated Content-Encoding values.
Definition HttpClient.h:62
Parsed response content-coding token view.
Definition HttpClient.h:40
Event slot storage used by HttpClientOperation to hand off backend notifications.
Definition HttpClient.h:409
Listener receiving response notifications during HttpClientOperation::poll.
Definition HttpClient.h:366
virtual void onError(Result error)
Called when the request fails.
Definition HttpClient.h:382
virtual void onResponseComplete()
Called when the response body completed successfully.
Definition HttpClient.h:378
virtual void onResponseHead(HttpClientResponse &response)
Called once the response status code and headers are available.
Definition HttpClient.h:371
virtual void onResponseBody(Span< const char > data)
Called for each response body chunk delivered by poll()
Definition HttpClient.h:375
Caller-owned memory for one HttpClientOperation.
Definition HttpClient.h:432
Span< char > responseBufferMemory
Optional; split equally into responseBuffers if non-empty.
Definition HttpClient.h:436
Optional notifier used by external adapters to wake up their own event loop.
Definition HttpClient.h:389
virtual void notifyHttpClientOperation(HttpClientOperation &operation)=0
Notifies an external adapter that the operation has queued new events.
One in-flight HTTP request/response operation.
Definition HttpClient.h:503
void setNotifier(HttpClientOperationNotifier *notifierValue)
Registers an optional notifier used by adapters such as HttpClientAsyncT.
Definition HttpClient.h:531
Result start(const HttpClientRequest &request, HttpClientResponse &response, HttpClientOperationListener *listener=nullptr)
Starts a new request on this operation.
Result poll(uint32_t timeoutMilliseconds=0)
Processes queued backend events and optionally waits for more work.
Pull-based provider for streamed request bodies.
Definition HttpClient.h:353
virtual Result pullRequestBody(Span< char > dest, size_t &bytesWritten, bool &endReached)=0
Writes the next request body chunk in dest.
Outgoing request body description.
Definition HttpClient.h:160
Framing
Transfer framing requested for the outgoing body.
Definition HttpClient.h:166
Extended request options grouped by transport concern.
Definition HttpClient.h:262
HTTP protocol preference for one request.
Definition HttpClient.h:226
Proxy policy for one request.
Definition HttpClient.h:243
StringSpan authorization
Optional exact Proxy-Authorization header value for Http
Definition HttpClient.h:253
StringSpan url
Required for Http, must use the http:// scheme.
Definition HttpClient.h:252
Mode
Definition HttpClient.h:245
@ NoProxy
Bypass proxies for this request.
Definition HttpClient.h:247
@ Default
Use the backend default proxy configuration.
Definition HttpClient.h:246
@ Http
Use url as an explicit HTTP proxy URL.
Definition HttpClient.h:248
StringSpan bypassList
Optional comma-separated proxy bypass list for Http
Definition HttpClient.h:254
Redirect handling policy for one request.
Definition HttpClient.h:196
Timeout policy for one request.
Definition HttpClient.h:213
TLS policy for one request.
Definition HttpClient.h:219
Configuration for an outgoing HTTP request.
Definition HttpClient.h:275
StringSpan url
Full URL including scheme (e.g. "https://example.com/path")
Definition HttpClient.h:289
Caller-owned response buffer descriptor for one HttpClientOperation.
Definition HttpClient.h:399
Parsed response metadata filled when headers arrive.
Definition HttpClient.h:304
Caller-owned cursor for iterating comma-separated Transfer-Encoding values.
Definition HttpClient.h:91
Parsed response transfer-coding token view.
Definition HttpClient.h:71
Reusable HTTP backend/session owner.
Definition HttpClient.h:448
static Result executeBlocking(const HttpClientRequest &request, HttpClientResponse &response, Span< char > bodyBuffer, size_t &bodyLength, const HttpClientOperationMemory &memory)
Convenience helper executing a request synchronously on top of HttpClientOperation::poll.