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;
208 transportPreflight = move(preflight);
217 externalConnector = move(connector);
232 transportShutdown = move(shutdown);
238 transportPreflight = {};
239 externalConnector = {};
241 transportShutdown = {};
270 Result
put(
AsyncEventLoop& loop, StringSpan url, Span<const char> body,
bool keepAlive =
false);
271 Result put(
AsyncEventLoop& loop, StringSpan url, StringSpan body,
bool keepAlive =
false)
273 return put(loop, url, body.toCharSpan(), keepAlive);
278 Result post(
AsyncEventLoop& loop, StringSpan url, StringSpan body,
bool keepAlive =
false)
280 return post(loop, url, body.toCharSpan(), keepAlive);
285 Result patch(
AsyncEventLoop& loop, StringSpan url, StringSpan body,
bool keepAlive =
false)
287 return patch(loop, url, body.toCharSpan(), keepAlive);
308 enum class BodyMode : uint8_t
320 bool keepAlive =
false;
321 bool autoSend =
false;
323 Span<const char> bodySpan;
325 BodyMode bodyMode = BodyMode::None;
326 uint64_t contentLength = 0;
328 Span<const Header> headers;
334 enum class State : uint8_t
343 Result startRequest(AsyncEventLoop& loop,
const RequestPreset& preset);
344 Result prepareRequest(
const RequestPreset& preset);
345 Result startPreparedRequest(
const RequestPreset& preset);
346 Result ensureConnected();
347 Result closeConnectionForReconnect();
348 Result beginReconnectClose();
349 Result continueReconnectAfterClose();
350 void clearReconnectCloseListeners();
351 Result beginExternalConnection();
352 Result beginSocketConnection();
353 Result beginResponseRead();
354 Result beginRequestSend();
355 Result onResponseBodyStreamRead();
356 Result validateActiveRequest()
const;
358 void completeTransportSetup(Result result);
359 [[nodiscard]] Result rememberConnectedOrigin();
361 void finalizeResponse(
bool finishBodyStream);
362 void closeConnection(
bool preserveReconnectListeners =
false);
363 void finishResponse();
364 void fail(Result error);
366 void onReconnectReadableClosed();
367 void onReconnectWritableClosed();
368 void onReconnectSocketReadableClosed();
369 void onReconnectSocketWritableClosed();
370 void onReconnectTransportShutdown(Result result);
372 void onConnected(AsyncSocketConnect::Result& result);
373 void onReadableError(Result result);
374 void onWritableError(Result result);
375 void onPipelineError(Result result);
376 void onReadableEnd();
377 void onHeadersBufferWritten(AsyncBufferView::ID bufferID);
378 void onResponseData(AsyncBufferView::ID bufferID);
379 void onResponseBodyData(AsyncBufferView::ID bufferID);
380 void onCompressedResponseBodyData(AsyncBufferView::ID bufferID);
381 void onCompressedResponseBodyWritten(AsyncBufferView::ID bufferID);
382 void onCompressedResponseBodyEnd();
383 void onCompressedResponseError(Result result);
385 [[nodiscard]]
bool canReuseConnectionFor(StringSpan protocol, StringSpan host, uint16_t port)
const;
386 [[nodiscard]]
bool responseMustNotHaveBody()
const;
387 [[nodiscard]]
bool responseHasKnownLength()
const;
388 [[nodiscard]] Result prepareResponseDecompression();
389 [[nodiscard]] Result startResponseStreams();
390 void detachResponseDecompression();
392 HttpConnectionBase* connection =
nullptr;
394 AsyncEventLoop* eventLoop =
nullptr;
395 HttpAsyncClientRequest* currentRequest =
nullptr;
397 HttpAsyncClientRequest request;
398 HttpAsyncClientResponse response;
399 AsyncSocketConnect connectAsync;
400 RequestPreset currentPreset;
402 SyncZLibTransformStream* responseDecoder =
nullptr;
403 bool responseDecoderActive =
false;
405 Function<Result(
const HttpURLParser&)> transportPreflight;
406 Function<Result(HttpAsyncClientExternalConnection&)> externalConnector;
407 Function<Result(HttpAsyncClientTransportSetup&)> transportSetup;
408 Function<Result(Function<
void(Result)>)> transportShutdown;
409 Function<void()> transportClose;
411 State state = State::Idle;
413 StringSpan currentProtocol;
414 char currentProtocolStorage[16] = {0};
416 StringSpan currentHost;
417 char currentHostStorage[256] = {0};
418 uint16_t currentPort = 0;
420 HttpURLParser currentURL;
421 uint32_t requestCount = 0;
423 bool hasOpenConnection =
false;
424 bool responseDelivered =
false;
425 bool responseFinalized =
false;
426 bool webSocketUpgraded =
false;
428 uint8_t reconnectClosuresPending = 0;
429 bool reconnectCloseInProgress =
false;
430 bool reconnectPending =
false;
432 AsyncReadableStream* reconnectReadableStream =
nullptr;
433 AsyncWritableStream* reconnectWritableStream =
nullptr;
435 AsyncReadableStream* reconnectSocketReadableStream =
nullptr;
436 AsyncWritableStream* reconnectSocketWritableStream =
nullptr;
Asynchronous I/O (files, sockets, timers, processes, fs events, threads wake-up) (see Async) AsyncEve...
Definition Async.h:1506
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:228
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:428
Incoming HTTP response received by the client.
Definition HttpConnection.h:259
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.
void setTransportPreflight(Function< Result(const HttpURLParser &)> &&preflight)
Sets an optional transport policy hook invoked after URL parsing and before DNS or socket activity.
Definition HttpAsyncClient.h:206
Result options(AsyncEventLoop &loop, StringSpan url, bool keepAlive=false)
Convenience wrapper for an OPTIONS request without a request body.
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:300
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 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:303
Result postMultipart(AsyncEventLoop &loop, StringSpan url, HttpMultipartWriter &writer, bool keepAlive=false)
Convenience wrapper for a multipart/form-data POST request.
void setTransportShutdown(Function< Result(Function< void(Result)>)> &&shutdown)
Sets an optional asynchronous hook that drains a transport before reconnecting to another origin.
Definition HttpAsyncClient.h:230
Result close()
Closes any active connection and releases references to the initialized storage.
void clearTransportSetup()
Clears the optional transport setup hook and restores default socket transport setup.
Definition HttpAsyncClient.h:236
void setExternalConnector(Function< Result(HttpAsyncClientExternalConnection &)> &&connector)
Sets an optional connector that owns DNS and connection establishment for future requests.
Definition HttpAsyncClient.h:215
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.
void setTransportSetup(Function< Result(HttpAsyncClientTransportSetup &)> &&setup)
Sets an optional transport setup hook invoked after TCP connect and before HTTP request bytes are sen...
Definition HttpAsyncClient.h:201
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:297
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.
void setTransportClose(Function< void()> &&close)
Sets an optional transport teardown hook invoked before HTTP destroys the connected socket streams.
Definition HttpAsyncClient.h:223
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:657
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