7#include "../Async/Async.h"
8#include "../AsyncStreams/AsyncRequestStreams.h"
9#include "../Common/StringSpan.h"
10#include "Internal/HttpFixedBufferWriter.h"
11#include "Internal/HttpParsedHeaders.h"
18enum class HttpBodyFramingKind : uint8_t
26enum class HttpContentEncoding : uint8_t
33SC_HTTP_EXPORT StringSpan httpContentEncodingName(HttpContentEncoding encoding);
34SC_HTTP_EXPORT Result httpContentEncodingFromHeader(StringSpan headerValue, HttpContentEncoding& encoding);
36struct HttpAsyncClient;
37struct SyncZLibTransformStream;
45 StringSpan contentType;
47 Span<const char> body;
50 static constexpr size_t MaxParts = 8;
54 Result setBoundary(StringSpan boundaryValue);
55 Result addField(StringSpan fieldName, StringSpan value);
56 Result addFile(StringSpan fieldName, StringSpan fileName, Span<const char> body,
57 StringSpan contentType =
"application/octet-stream");
59 [[nodiscard]] StringSpan getBoundary()
const {
return boundary; }
60 [[nodiscard]]
size_t getNumParts()
const {
return numParts; }
61 [[nodiscard]]
const Part& getPart(
size_t idx)
const {
return parts[idx]; }
62 [[nodiscard]]
size_t getContentLength()
const;
67 char boundaryStorage[71] = {0};
83 void setHeaderMemory(Span<char> memory) { headerMemory = memory; }
85 [[nodiscard]] Span<char> getHeaderMemory()
const {
return headerMemory; }
88 void resetTransportStreams();
90 [[nodiscard]]
AsyncReadableStream& getReadableTransportStream() {
return *readableTransportStream; }
91 [[nodiscard]]
AsyncWritableStream& getWritableTransportStream() {
return *writableTransportStream; }
93 [[nodiscard]]
const AsyncReadableStream& getReadableTransportStream()
const {
return *readableTransportStream; }
94 [[nodiscard]]
const AsyncWritableStream& getWritableTransportStream()
const {
return *writableTransportStream; }
99 Span<char> headerMemory;
113 Result begin(
AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
116 void failBody(Result result);
118 Function<Result()> onReadRequest;
122 virtual Result asyncRead()
override;
123 virtual Result asyncResumeReading()
override;
133 [[nodiscard]]
bool getKeepAlive()
const {
return parsedHeaders.parser.connectionKeepAlive; }
157 [[nodiscard]]
bool getHeader(StringSpan headerName, StringSpan& value)
const;
171 [[nodiscard]] Span<char> getUnusedHeaderMemory()
const {
return parsedHeaders.availableHeader; }
173 Result initBodyStream(
AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
174 Result startBodyStream();
176 void finishBodyStream();
177 void failBodyStream(Result result);
178 void abortBodyStream();
179 Result prepareBodyStream(
AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest,
180 bool allowCloseDelimited);
182 bool allowTrailingData);
184 void setBodyBytesRemaining(uint64_t value) { bodyBytesRemaining = value; }
185 void setBodyFramingKind(HttpBodyFramingKind value) { bodyFramingKind = value; }
186 void setBodyComplete(
bool value) { bodyComplete = value; }
187 void attachReadableStream(AsyncReadableStream& stream) { readableStream = &stream; }
199 bool stopAtHeadersEnd,
bool unshiftPendingBodyToStream =
true);
204 enum class ChunkedState : uint8_t
217 HttpParsedHeaders parsedHeaders;
218 Span<char> headerMemory;
220 uint64_t bodyBytesRemaining = 0;
221 HttpBodyFramingKind bodyFramingKind = HttpBodyFramingKind::None;
222 bool bodyComplete =
true;
223 bool bodyStreamStarted =
false;
224 BodyStream bodyStream;
225 ChunkedState chunkedState = ChunkedState::Size;
226 uint64_t chunkedChunkSize = 0;
227 uint64_t chunkedBytesRemaining = 0;
228 bool chunkedSizeHasDigits =
false;
238 StringSpan
getURL()
const {
return url; }
248 void setHeaderMemory(Span<char> memory);
251 Result writeHeaders(
const uint32_t maxHeaderSize, Span<const char> readData,
AsyncReadableStream& stream,
263 void reset(Span<char> memory);
264 Result writeHeaders(uint32_t maxHeaderSize, Span<const char> readData,
AsyncReadableStream& stream,
266 BodyStream& rawBodyStream() {
return bodyStream; }
293 bool finalChunkStarted =
false;
294 bool finalChunkWritten =
false;
296 char headerStorage[20] = {0};
304 Result
addHeader(StringSpan headerName, StringSpan headerValue);
331 [[nodiscard]]
bool getKeepAlive()
const {
return forceDisableKeepAlive ? false : keepAlive; }
334 enum class KnownHeader : uint8_t
346 void setHeaderMemory(Span<char> memory);
347 void setWritableStream(AsyncWritableStream& stream)
349 destinationStream = &stream;
350 writableStream = &stream;
353 [[nodiscard]]
bool hasHeader(KnownHeader header)
const;
354 [[nodiscard]]
bool hasSentHeaders()
const {
return headersSent; }
355 [[nodiscard]]
bool hasEnded()
const {
return endCalled; }
356 [[nodiscard]]
bool isChunkedTransferEncodingEnabled()
const {
return chunkedTransferEncodingEnabled; }
358 HttpFixedBufferWriter responseHeaders;
359 Span<char> headerMemory;
361 bool headersSent =
false;
362 bool endCalled =
false;
364 bool forceDisableKeepAlive =
false;
365 bool keepAlive =
true;
366 bool connectionHeaderAdded =
false;
367 bool hostHeaderAdded =
false;
368 bool userAgentHeaderAdded =
false;
369 bool contentLengthAdded =
false;
370 bool contentTypeAdded =
false;
371 bool transferEncodingAdded =
false;
372 bool contentEncodingAdded =
false;
373 bool acceptEncodingAdded =
false;
374 bool chunkedTransferEncodingEnabled =
false;
391 Result
startBody(
int httpCode, uint64_t contentLength, StringSpan contentType = {});
395 Result
sendBytes(
int httpCode, Span<const char> body, StringSpan contentType = {});
399 Result
sendBody(
int httpCode, StringSpan body, StringSpan contentType = {});
429 enum class BodyType : uint8_t
441 Result setExpectedBodyLength(uint64_t value);
442 Result setBody(Span<const char> value);
443 Result setBody(StringSpan value) {
return setBody(value.toCharSpan()); }
447 HttpContentEncoding encoding);
453 [[nodiscard]] StringSpan getRequestTarget()
const {
return url; }
454 [[nodiscard]] StringSpan getURL()
const {
return url; }
455 [[nodiscard]] BodyType getBodyType()
const {
return bodyType; }
456 [[nodiscard]] uint64_t getContentLength()
const {
return contentLength; }
457 [[nodiscard]]
bool usesChunkedTransferEncoding()
const {
return chunkedTransferEncodingEnabled; }
458 [[nodiscard]] HttpContentEncoding getContentEncoding()
const {
return contentEncoding; }
463 void setDefaultHost(StringSpan value) { defaultHost = value; }
465 [[nodiscard]]
bool hasTransferEncodingHeader()
const {
return hasHeader(KnownHeader::TransferEncoding); }
466 [[nodiscard]]
bool hasAcceptEncodingHeader()
const {
return hasHeader(KnownHeader::AcceptEncoding); }
470 [[nodiscard]]
const HttpMultipartWriter* getMultipartWriter()
const {
return multipartWriter; }
471 [[nodiscard]] Span<const char> getBodySpan()
const {
return bodySpan; }
477 BodyType bodyType = BodyType::None;
478 Span<const char> bodySpan;
479 uint64_t contentLength = 0;
480 HttpContentEncoding contentEncoding = HttpContentEncoding::Identity;
482 StringSpan defaultHost;
493 struct SC_HTTP_EXPORT
ID
495 size_t getIndex()
const {
return index; }
515 Result
sendBodyCopy(
int httpCode, StringSpan body, StringSpan contentType = {});
526 uint32_t requestCount = 0;
537 State state = State::Inactive;
539 bool webSocketUpgraded =
false;
543template <
typename Type>
553 constexpr SpanWithStride(
void* data,
size_t sizeInElements,
size_t strideInBytes)
554 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
557 template <
typename U>
559 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
562 [[nodiscard]]
constexpr size_t sizeInElements()
const {
return sizeElements; }
563 [[nodiscard]]
constexpr bool empty()
const {
return sizeElements == 0; }
565 template <
typename U>
566 SpanWithStride<U> castTo()
568 return {
static_cast<U*
>(
reinterpret_cast<Type*
>(data)), sizeElements, strideInBytes};
571 [[nodiscard]] Type& operator[](
size_t idx)
573 return *
reinterpret_cast<Type*
>(
reinterpret_cast<char*
>(data) + idx * strideInBytes);
576 [[nodiscard]]
const Type& operator[](
size_t idx)
const
578 return *
reinterpret_cast<const Type*
>(
reinterpret_cast<const char*
>(data) + idx * strideInBytes);
584 size_t strideInBytes;
592 size_t readQueueSize = 3;
593 size_t writeQueueSize = 3;
594 size_t buffersQueueSize = 6;
595 size_t headerBytesLength = 8 * 1024;
596 size_t streamBytesLength = 512 * 1024;
601 Span<AsyncReadableStream::Request> allReadQueue;
602 Span<AsyncWritableStream::Request> allWriteQueue;
604 Span<AsyncBufferView> allBuffers;
606 Span<char> allHeaders;
607 Span<char> allStreams;
630 return connections[connectionID.index];
645 size_t numConnections = 0;
648 size_t highestActiveConnection = 0;
652template <
int ReadQueue,
int WriteQueue,
int HeaderBytes,
int StreamBytes,
int ExtraBuffers,
typename BaseClass>
660 char headerStorage[HeaderBytes];
661 char streamStorage[StreamBytes];
665 constexpr const size_t NumSlices = ReadQueue;
666 constexpr const size_t SliceLength = StreamBytes / NumSlices;
668 Span<char> memory = streamStorage;
669 for (
size_t idx = 0; idx < NumSlices; ++idx)
672 (void)memory.sliceStartLength(idx * SliceLength, SliceLength, slice);
673 buffers[idx] = slice;
676 this->setHeaderMemory(headerStorage);
678 this->readableSocketStream.setReadQueue(readQueue);
679 this->writableSocketStream.setWriteQueue(writeQueue);
Definition AsyncStreams.h:66
A Span of bytes memory to be read or written by async streams.
Definition AsyncStreams.h:64
void setReusable(bool reusable)
Tags this AsyncBufferView as reusable after its refCount goes to zero.
Definition AsyncStreams.h:105
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:177
void setBuffers(Span< AsyncBufferView > newBuffers)
Sets memory for the new buffers.
Definition AsyncStreams.h:207
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:558
Definition AsyncStreams.h:233
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:228
Definition AsyncStreams.h:371
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:364
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:428
Incoming HTTP response received by the client.
Definition HttpConnection.h:259
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:75
Async Http Server.
Definition HttpAsyncServer.h:52
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:73
Definition HttpConnection.h:494
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:490
Result sendBodyCopy(int httpCode, StringSpan body, StringSpan contentType={})
Sends a fixed-size response body by copying it into this connection's async buffer pool.
bool isWebSocketUpgraded() const
Returns true after the HTTP layer handed this connection to WebSocket code.
Definition HttpConnection.h:512
void reset()
Prepare this client for re-use, marking it as Inactive.
void markWebSocketUpgraded()
Marks this HTTP connection as handed off to a WebSocket owner after a successful upgrade.
Definition HttpConnection.h:509
ID getConnectionID() const
The ID used to find this client in HttpConnectionsPool.
Definition HttpConnection.h:506
Result sendTextCopy(int httpCode, StringSpan body)
Sends a text/plain; charset=utf-8 response body by copying it into this connection's async buffer poo...
Result sendJsonCopy(int httpCode, StringSpan body)
Sends an application/json response body by copying it into this connection's async buffer pool.
Definition HttpConnection.h:591
Definition HttpConnection.h:600
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:589
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:619
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:625
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:634
Result init(SpanWithStride< HttpConnection > connectionsStorage)
Initializes the server with memory buffers for connections and headers.
bool activateNew(HttpConnection::ID &connectionID)
Finds an available connection (if any), activates it and returns its ID to use with getConnection(id)
HttpConnection & getConnection(HttpConnection::ID connectionID)
Returns a connection by ID.
Definition HttpConnection.h:628
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:622
Result close()
Closes the server, removing references to the memory buffers passed during init.
bool deactivate(HttpConnection::ID connectionID)
De-activates a connection previously returned by activateNew.
Definition HttpConnection.h:110
Incoming message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:108
bool getKeepAlive() const
Gets whether the other party requested the connection to stay alive.
Definition HttpConnection.h:133
const AsyncReadableStream & getReadableStream() const
Obtains the readable stream for the message body.
AsyncReadableStream & getReadableStream()
Obtains the readable stream for the message body.
bool isMultipart() const
Checks if the request is a multipart/form-data request.
const HttpParser & getParser() const
Gets the associated HttpParser.
Definition HttpConnection.h:127
bool getHeader(StringSpan headerName, StringSpan &value) const
Gets the value of a specific header (case-insensitive name matching)
StringSpan getVersion() const
Gets the parsed HTTP protocol version token, for example HTTP/1.1
size_t getHeadersLength() const
Gets the length of the headers in bytes.
StringSpan getBoundary() const
Gets the multipart boundary string (if isMultipart() returns true)
bool findParserToken(HttpParser::Token token, StringSpan &res) const
Finds a specific HttpParser::Result in the list of parsed header.
Result consumeBodyBytes(size_t bytes)
Decrements the remaining body bytes after consuming data.
bool isBodyComplete() const
Returns true once the full body has been received according to its framing.
Definition HttpConnection.h:145
uint64_t getBodyBytesRemaining() const
Returns how many body bytes are still expected for this message.
Definition HttpConnection.h:142
bool hasReceivedHeaders() const
Returns true once the incoming message headers have been parsed.
Definition HttpConnection.h:130
HttpBodyFramingKind getBodyFramingKind() const
Returns the effective framing mode for the incoming body.
Definition HttpConnection.h:139
Result writeHeaders(const uint32_t maxHeaderSize, Span< const char > readData, AsyncReadableStream &stream, AsyncBufferView::ID bufferID, const char *outOfSpaceError, const char *sizeExceededError, bool stopAtHeadersEnd, bool unshiftPendingBodyToStream=true)
Parses an incoming slice of data eventually copying it to the availableHeader.
Definition HttpConnection.h:42
Definition HttpConnection.h:40
Definition HttpConnection.h:273
virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> cb) override
Function that every stream must define to implement its custom write operation.
virtual bool canEndWritable() override
Allows keeping a writable in ENDING state until it has finished flushing all pending data.
Outgoing message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:271
Result setChunkedTransferEncoding()
Enables chunked transfer-encoding for subsequent body writes.
bool getKeepAlive() const
Gets whether the connection should be kept alive after this response.
Definition HttpConnection.h:331
Result end()
Finalizes the writable stream after sending all in progress writes.
void reset()
Resets this object for it to be re-usable.
Result sendHeaders(Function< void(AsyncBufferView::ID)> callback={})
Start sending response headers, before sending any data.
Result addContentLength(uint64_t value)
Adds a formatted Content-Length header without caller-side temporary formatting.
Result addHeader(StringSpan headerName, StringSpan headerValue)
Writes an http header to this response.
void setKeepAlive(bool keepAlive)
Sets whether to keep the connection alive after this response.
AsyncWritableStream & getWritableStream()
Obtain writable stream for sending content back to connected client.
Definition HttpConnection.h:322
Incremental HTTP request or response parser.
Definition HttpParser.h:16
Token
One possible Token reported by the parser.
Definition HttpParser.h:46
Method
Method of the current request / response.
Definition HttpParser.h:19
Type
Type of the stream to be parsed (Request or Response)
Definition HttpParser.h:63
Incoming HTTP request received by the server.
Definition HttpConnection.h:233
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:238
void reset()
Resets this object for it to be re-usable.
StringSpan getRequestTarget() const
Gets the raw request target from the request line.
Definition HttpConnection.h:235
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:383
Result sendJson(int httpCode, StringSpan body)
Sends a caller-owned application/json response body.
Result startResponse(int httpCode)
Starts the response with a http standard code (200 OK, 404 NOT FOUND etc.)
Result startResponse(int httpCode, StringSpan reasonPhrase)
Starts the response with an explicit status code and reason phrase.
Result sendMethodNotAllowed(StringSpan allow)
Sends a 405 Method Not Allowed response with an Allow header and Content-Length: 0.
Result sendRedirect(int httpCode, StringSpan location)
Sends a 3xx redirect response with a Location header and Content-Length: 0.
Result sendBody(int httpCode, StringSpan body, StringSpan contentType={})
Sends a caller-owned fixed-size body response.
Result sendText(int httpCode, StringSpan body)
Sends a caller-owned text/plain; charset=utf-8 response body.
Result sendBytes(int httpCode, Span< const char > body, StringSpan contentType={})
Sends a caller-owned fixed-size byte response.
Result sendEmpty(int httpCode)
Sends an empty response with Content-Length: 0.
Result startBody(int httpCode, uint64_t contentLength, StringSpan contentType={})
Starts a fixed-size body response and adds Content-Length plus optional Content-Type.
Adds compile-time configurable read and write queues to any class subclassing HttpConnectionBase.
Definition HttpConnection.h:654
Low-level OS socket handle.
Definition Socket.h:167
View over a contiguous sequence of items with a custom stride between elements.
Definition HttpConnection.h:545
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:553
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:547