4#include "HttpConnection.h"
6#include "HttpURLParser.h"
13struct HttpWebSocketTransportView;
29 SocketDescriptor::Handle nativeSocket = SocketDescriptor::Invalid;
31 Function<void(Result)> complete;
32 Function<void(Result)> fail;
47 Function<void(Result)> complete;
48 Function<void(Result)> fail;
51template <
int ReadQueue,
int WriteQueue,
int HeaderBytes,
int StreamBytes>
53 :
public HttpStaticConnection<ReadQueue, WriteQueue, HeaderBytes, StreamBytes, 8, HttpConnectionBase>
55 static constexpr int ExtraBuffers = 8;
59 this->readableSocketStream.setAutoDestroy(
false);
60 this->writableSocketStream.setAutoDestroy(
false);
94 enum class BodyMode : uint8_t
105 Span<const Header> headers;
107 Span<const char> body;
111 uint64_t bodyLength = 0;
113 BodyMode bodyMode = BodyMode::None;
114 bool keepAlive =
false;
120 keepAlive = newKeepAlive;
126 headers = newHeaders;
132 keepAlive = newKeepAlive;
139 bodyStream =
nullptr;
140 multipartWriter =
nullptr;
142 bodyMode = BodyMode::None;
150 bodyLength = newBody.sizeInBytes();
151 bodyMode = BodyMode::Span;
155 RequestOptions& setBody(StringSpan newBody) {
return setBody(newBody.toCharSpan()); }
159 return setBody(StringSpan::fromNullTerminated(newBody, StringEncoding::Ascii));
165 bodyStream = &newBodyStream;
166 bodyLength = newBodyLength;
167 bodyMode = BodyMode::Stream;
174 multipartWriter = &newMultipartWriter;
175 bodyMode = BodyMode::Multipart;
203 SC_TRY(checkTransportMutation(owner));
204 transportSetup = move(setup);
213 SC_TRY(checkTransportMutation(owner));
214 transportPreflight = move(preflight);
223 const void* owner =
nullptr)
225 SC_TRY(checkTransportMutation(owner));
226 externalConnector = move(connector);
235 SC_TRY(checkTransportMutation(owner));
236 transportClose = move(close);
247 SC_TRY(checkTransportMutation(owner));
248 transportShutdown = move(shutdown);
289 Result
put(
AsyncEventLoop& loop, StringSpan url, Span<const char> body,
bool keepAlive =
false);
290 Result put(
AsyncEventLoop& loop, StringSpan url, StringSpan body,
bool keepAlive =
false)
292 return put(loop, url, body.toCharSpan(), keepAlive);
297 Result post(
AsyncEventLoop& loop, StringSpan url, StringSpan body,
bool keepAlive =
false)
299 return post(loop, url, body.toCharSpan(), keepAlive);
304 Result patch(
AsyncEventLoop& loop, StringSpan url, StringSpan body,
bool keepAlive =
false)
306 return patch(loop, url, body.toCharSpan(), keepAlive);
325 Result checkTransportMutation(
const void* owner)
const;
326 Result checkTransportQuiescence()
const;
330 enum class BodyMode : uint8_t
342 bool keepAlive =
false;
343 bool autoSend =
false;
345 Span<const char> bodySpan;
347 BodyMode bodyMode = BodyMode::None;
348 uint64_t contentLength = 0;
350 Span<const Header> headers;
356 enum class State : uint8_t
365 Result startRequest(AsyncEventLoop& loop,
const RequestPreset& preset);
366 Result prepareRequest(
const RequestPreset& preset);
367 Result startPreparedRequest(
const RequestPreset& preset);
368 Result ensureConnected();
369 Result closeConnectionForReconnect();
370 Result beginReconnectClose();
371 Result continueReconnectAfterClose();
372 void clearReconnectCloseListeners();
373 Result beginExternalConnection();
374 Result beginSocketConnection();
375 Result beginResponseRead();
376 Result beginRequestSend();
377 Result onResponseBodyStreamRead();
378 Result validateActiveRequest()
const;
380 void completeTransportSetup(Result result);
381 [[nodiscard]] Result rememberConnectedOrigin();
383 void finalizeResponse(
bool finishBodyStream);
384 void closeConnection(
bool preserveReconnectListeners =
false);
385 void finishResponse();
386 void fail(Result error);
388 void onReconnectReadableClosed();
389 void onReconnectWritableClosed();
390 void onReconnectSocketReadableClosed();
391 void onReconnectSocketWritableClosed();
392 void onReconnectTransportShutdown(Result result);
394 void onConnected(AsyncSocketConnect::Result& result);
395 void onReadableError(Result result);
396 void onWritableError(Result result);
397 void onPipelineError(Result result);
398 void onReadableEnd();
399 void onHeadersBufferWritten(AsyncBufferView::ID bufferID);
400 void onResponseData(AsyncBufferView::ID bufferID);
401 void onResponseBodyData(AsyncBufferView::ID bufferID);
402 void onCompressedResponseBodyData(AsyncBufferView::ID bufferID);
403 void onCompressedResponseBodyWritten(AsyncBufferView::ID bufferID);
404 void onCompressedResponseBodyEnd();
405 void onCompressedResponseError(Result result);
407 [[nodiscard]]
bool canReuseConnectionFor(StringSpan protocol, StringSpan host, uint16_t port)
const;
408 [[nodiscard]]
bool responseMustNotHaveBody()
const;
409 [[nodiscard]]
bool responseHasKnownLength()
const;
410 [[nodiscard]] Result prepareResponseDecompression();
411 [[nodiscard]] Result startResponseStreams();
412 void detachResponseDecompression();
414 HttpConnectionBase* connection =
nullptr;
416 AsyncEventLoop* eventLoop =
nullptr;
417 HttpAsyncClientRequest* currentRequest =
nullptr;
419 HttpAsyncClientRequest request;
420 HttpAsyncClientResponse response;
421 AsyncSocketConnect connectAsync;
422 RequestPreset currentPreset;
424 SyncZLibTransformStream* responseDecoder =
nullptr;
425 bool responseDecoderActive =
false;
427 Function<Result(
const HttpURLParser&)> transportPreflight;
428 Function<Result(HttpAsyncClientExternalConnection&)> externalConnector;
429 Function<Result(HttpAsyncClientTransportSetup&)> transportSetup;
430 Function<Result(Function<
void(Result)>)> transportShutdown;
431 Function<void()> transportClose;
433 const void* transportOwner =
nullptr;
435 uint32_t transportCallbackDepth = 0;
437 State state = State::Idle;
439 StringSpan currentProtocol;
440 char currentProtocolStorage[16] = {0};
442 StringSpan currentHost;
443 char currentHostStorage[256] = {0};
444 uint16_t currentPort = 0;
446 HttpURLParser currentURL;
447 uint32_t requestCount = 0;
449 bool hasOpenConnection =
false;
450 bool responseDelivered =
false;
451 bool responseFinalized =
false;
452 bool webSocketUpgraded =
false;
454 uint8_t reconnectClosuresPending = 0;
455 bool reconnectCloseInProgress =
false;
456 bool reconnectPending =
false;
458 AsyncReadableStream* reconnectReadableStream =
nullptr;
459 AsyncWritableStream* reconnectWritableStream =
nullptr;
461 AsyncReadableStream* reconnectSocketReadableStream =
nullptr;
462 AsyncWritableStream* reconnectSocketWritableStream =
nullptr;
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1517
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:229
Definition HttpAsyncClient.h:54
Connection request offered to an external transport before Http performs DNS or creates a socket.
Definition HttpAsyncClient.h:41
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:427
Incoming HTTP response received by the client.
Definition HttpConnection.h:258
Mutable transport setup view used by HttpAsyncClient after the TCP socket connects.
Definition HttpAsyncClient.h:23
Definition HttpAsyncClient.h:93
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:85
Result deleteRequest(AsyncEventLoop &loop, StringSpan url, bool keepAlive=false)
Convenience wrapper for a DELETE request without a request body.
Result releaseTransport(const void *owner)
Clears hooks and releases only the matching owner's claim on a quiescent client.
Result options(AsyncEventLoop &loop, StringSpan url, bool keepAlive=false)
Convenience wrapper for an OPTIONS request without a request body.
Result setTransportPreflight(Function< Result(const HttpURLParser &)> &&preflight, const void *owner=nullptr)
Sets an optional transport policy hook invoked after URL parsing and before DNS or socket activity.
Definition HttpAsyncClient.h:211
void clearResponseDecompression()
Disables response decompression for future requests.
Definition HttpAsyncClient.h:195
Function< void(HttpAsyncClientResponse &)> onResponse
Called after the response headers have been parsed.
Definition HttpAsyncClient.h:319
Result patch(AsyncEventLoop &loop, StringSpan url, Span< const char > body, bool keepAlive=false)
Convenience wrapper for a PATCH request with a fixed in-memory body.
Result detachWebSocketTransport(HttpWebSocketTransportView &transport)
Hands the connected socket streams to a WebSocket owner after a validated 101 response.
Result setExternalConnector(Function< Result(HttpAsyncClientExternalConnection &)> &&connector, const void *owner=nullptr)
Sets an optional connector that owns DNS and connection establishment for future requests.
Definition HttpAsyncClient.h:222
Result setTransportSetup(Function< Result(HttpAsyncClientTransportSetup &)> &&setup, const void *owner=nullptr)
Sets an optional transport setup hook invoked after TCP connect and before HTTP request bytes are sen...
Definition HttpAsyncClient.h:201
Result head(AsyncEventLoop &loop, StringSpan url, bool keepAlive=false)
Convenience wrapper for a HEAD request without a request body.
Result start(AsyncEventLoop &loop, HttpParser::Method method, StringSpan url, bool keepAlive=false)
Starts a request that must be configured inside onPrepareRequest onPrepareRequest must send the heade...
Function< void(Result)> onError
Called on connection, protocol or streaming errors.
Definition HttpAsyncClient.h:322
Result postMultipart(AsyncEventLoop &loop, StringSpan url, HttpMultipartWriter &writer, bool keepAlive=false)
Convenience wrapper for a multipart/form-data POST request.
Result close()
Closes any active connection and releases references to the initialized storage.
Result setTransportShutdown(Function< Result(Function< void(Result)>)> &&shutdown, const void *owner=nullptr)
Sets an optional asynchronous hook that drains a transport before reconnecting to another origin.
Definition HttpAsyncClient.h:245
Result get(AsyncEventLoop &loop, StringSpan url, bool keepAlive=false)
Convenience wrapper for a GET request without a request body.
Result sendRequest(AsyncEventLoop &loop, const RequestOptions &options)
Starts an auto-sent request described by caller-owned request options.
Result claimTransport(const void *owner)
Claims the complete transport hook group on a quiescent client without existing hooks or an owner.
Result init(HttpConnectionBase &storage)
Initializes the client with caller-provided connection storage The storage must outlive the client an...
Result post(AsyncEventLoop &loop, StringSpan url, Span< const char > body, bool keepAlive=false)
Convenience wrapper for a POST request with a fixed in-memory body.
void setResponseDecompression(SyncZLibTransformStream &decoder)
Enables opt-in gzip/deflate response decompression.
Definition HttpAsyncClient.h:192
Function< void(HttpAsyncClientRequest &)> onPrepareRequest
Called after the request has been created and can still be customized.
Definition HttpAsyncClient.h:316
Result clearTransportSetup(const void *owner=nullptr)
Clears the optional transport setup hook and restores default socket transport setup.
Result put(AsyncEventLoop &loop, StringSpan url, Span< const char > body, bool keepAlive=false)
Convenience wrapper for a PUT request with a fixed in-memory body.
Result setTransportClose(Function< void()> &&close, const void *owner=nullptr)
Sets an optional transport teardown hook invoked before HTTP destroys the connected socket streams.
Definition HttpAsyncClient.h:233
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:73
Definition HttpConnection.h:40
Method
Method of the current request / response.
Definition HttpParser.h:19
Adds compile-time configurable read and write queues to any class subclassing HttpConnectionBase.
Definition HttpConnection.h:656
Parse an URL splitting it into its base components.
Definition HttpURLParser.h:71
Minimal transport handoff shape for later HTTP upgrade integration.
Definition HttpWebSocket.h:67