Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
HttpConnection.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "HttpExport.h"
5#include "HttpParser.h"
6
7#include "../Async/Async.h"
8#include "../AsyncStreams/AsyncRequestStreams.h"
9#include "../Foundation/StringSpan.h"
10#include "Internal/HttpFixedBufferWriter.h"
11#include "Internal/HttpParsedHeaders.h"
12
13namespace SC
14{
17
18enum class HttpBodyFramingKind : uint8_t
19{
20 None,
21 ContentLength,
22 Chunked,
23 CloseDelimited,
24};
25
26enum class HttpContentEncoding : uint8_t
27{
28 Identity,
29 GZip,
30 Deflate,
31};
32
33SC_HTTP_EXPORT StringSpan httpContentEncodingName(HttpContentEncoding encoding);
34SC_HTTP_EXPORT Result httpContentEncodingFromHeader(StringSpan headerValue, HttpContentEncoding& encoding);
35
36struct HttpAsyncClient;
37struct SyncZLibTransformStream;
38
39struct SC_HTTP_EXPORT HttpMultipartWriter
40{
41 struct Part
42 {
43 StringSpan partName;
44 StringSpan fileName;
45 StringSpan contentType;
46
48 };
49
50 static constexpr size_t MaxParts = 8;
51
52 void reset();
53
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");
58
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;
63
64 private:
65 Part parts[MaxParts];
66 size_t numParts = 0;
67 char boundaryStorage[71] = {0};
68 StringSpan boundary;
69};
70
72struct SC_HTTP_EXPORT HttpConnectionBase
73{
76
77 ReadableSocketStream readableSocketStream;
78 WritableSocketStream writableSocketStream;
79 AsyncBuffersPool buffersPool;
80 AsyncPipeline pipeline;
81 SocketDescriptor socket;
82
83 void setHeaderMemory(Span<char> memory) { headerMemory = memory; }
84
85 [[nodiscard]] Span<char> getHeaderMemory() const { return headerMemory; }
86
87 void reset();
88
89 protected:
90 Span<char> headerMemory;
91};
92
94struct SC_HTTP_EXPORT HttpIncomingMessage
95{
96 struct SC_HTTP_EXPORT BodyStream : public AsyncReadableStream
97 {
98 BodyStream();
99
100 Result begin(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
101 bool pushBodyData(AsyncBufferView::ID bufferID, size_t sizeInBytes);
102 void finishBody();
103 void failBody(Result result);
104
105 Function<Result()> onReadRequest;
106 Request queue[4];
107
108 private:
109 virtual Result asyncRead() override;
110 virtual Result asyncResumeReading() override;
111 };
112
114 const HttpParser& getParser() const { return parsedHeaders.parser; }
115
117 [[nodiscard]] bool hasReceivedHeaders() const { return parsedHeaders.headersEndReceived; }
118
120 [[nodiscard]] bool getKeepAlive() const { return parsedHeaders.parser.connectionKeepAlive; }
121
123 [[nodiscard]] StringSpan getVersion() const;
124
126 [[nodiscard]] HttpBodyFramingKind getBodyFramingKind() const { return bodyFramingKind; }
127
129 [[nodiscard]] uint64_t getBodyBytesRemaining() const { return bodyBytesRemaining; }
130
132 [[nodiscard]] bool isBodyComplete() const { return bodyComplete; }
133
135 [[nodiscard]] bool isMultipart() const;
136
138 [[nodiscard]] StringSpan getBoundary() const;
139
144 [[nodiscard]] bool getHeader(StringSpan headerName, StringSpan& value) const;
145
148
151
154
155 protected:
156 void resetIncoming(HttpParser::Type type, Span<char> memory);
157
158 [[nodiscard]] Span<char> getUnusedHeaderMemory() const { return parsedHeaders.availableHeader; }
159
160 Result initBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
161 Result startBodyStream();
162 bool pushBodyData(AsyncBufferView::ID bufferID, size_t sizeInBytes);
163 void finishBodyStream();
164 void failBodyStream(Result result);
165 void abortBodyStream();
166 Result prepareBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest,
167 bool allowCloseDelimited);
168 Result processBodyData(AsyncReadableStream& sourceStream, AsyncBufferView::ID bufferID, Span<const char> readData,
169 bool allowTrailingData);
170
171 void setBodyBytesRemaining(uint64_t value) { bodyBytesRemaining = value; }
172 void setBodyFramingKind(HttpBodyFramingKind value) { bodyFramingKind = value; }
173 void setBodyComplete(bool value) { bodyComplete = value; }
174 void attachReadableStream(AsyncReadableStream& stream) { readableStream = &stream; }
175
180 [[nodiscard]] bool findParserToken(HttpParser::Token token, StringSpan& res) const;
181
184 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
185 AsyncBufferView::ID bufferID, const char* outOfSpaceError, const char* sizeExceededError,
186 bool stopAtHeadersEnd, bool unshiftPendingBodyToStream = true);
187
189 [[nodiscard]] size_t getHeadersLength() const;
190
191 enum class ChunkedState : uint8_t
192 {
193 Size,
194 SizeExtension,
195 SizeLF,
196 Data,
197 DataCR,
198 DataLF,
199 TrailerLineStart,
200 TrailerEndLF,
201 Finished,
202 };
203
204 HttpParsedHeaders parsedHeaders;
205 Span<char> headerMemory;
206 AsyncReadableStream* readableStream = nullptr;
207 uint64_t bodyBytesRemaining = 0;
208 HttpBodyFramingKind bodyFramingKind = HttpBodyFramingKind::None;
209 bool bodyComplete = true;
210 bool bodyStreamStarted = false;
211 BodyStream bodyStream;
212 ChunkedState chunkedState = ChunkedState::Size;
213 uint64_t chunkedChunkSize = 0;
214 uint64_t chunkedBytesRemaining = 0;
215 bool chunkedSizeHasDigits = false;
216};
217
219struct SC_HTTP_EXPORT HttpRequest : public HttpIncomingMessage
220{
222 StringSpan getRequestTarget() const { return url; }
223
225 StringSpan getURL() const { return url; }
226
228 void reset();
229
230 private:
231 friend struct HttpConnectionsPool;
232 friend struct HttpResponse;
233 friend struct HttpAsyncServer;
234
235 void setHeaderMemory(Span<char> memory);
236
238 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
239 AsyncBufferView::ID bufferID);
240
241 StringSpan url;
242};
243
245struct SC_HTTP_EXPORT HttpAsyncClientResponse : public HttpIncomingMessage
246{
247 private:
248 friend struct HttpAsyncClient;
249
250 void reset(Span<char> memory);
251 Result writeHeaders(uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
252 AsyncBufferView::ID bufferID);
253 BodyStream& rawBodyStream() { return bodyStream; }
254};
255
257struct SC_HTTP_EXPORT HttpOutgoingMessage
258{
259 struct SC_HTTP_EXPORT ChunkedWritableStream : public AsyncWritableStream
260 {
262
263 Result init(AsyncBuffersPool& buffersPool, AsyncWritableStream& destination);
264
265 protected:
266 virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function<void(AsyncBufferView::ID)> cb) override;
267 virtual bool canEndWritable() override;
268
269 private:
270 void onChunkHeaderWritten(AsyncBufferView::ID);
271 void onChunkBodyWritten(AsyncBufferView::ID);
272 void onChunkTerminatorWritten(AsyncBufferView::ID);
273 void onFinalChunkWritten(AsyncBufferView::ID);
274
275 AsyncWritableStream* destination = nullptr;
276
277 AsyncBufferView::ID currentBodyBufferID;
278 Function<void(AsyncBufferView::ID)> currentBodyCallback;
279
280 bool finalChunkStarted = false;
281 bool finalChunkWritten = false;
282
283 char headerStorage[20] = {0};
284
285 Request queue[4];
286 };
287
291 Result addHeader(StringSpan headerName, StringSpan headerValue);
292
295
298
300 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
301
303 void reset();
304
307
309 AsyncWritableStream& getWritableStream() { return *writableStream; }
310
314 void setKeepAlive(bool keepAlive);
315
318 [[nodiscard]] bool getKeepAlive() const { return forceDisableKeepAlive ? false : keepAlive; }
319
320 protected:
321 enum class KnownHeader : uint8_t
322 {
323 Connection,
324 Host,
325 UserAgent,
326 ContentLength,
327 ContentType,
328 TransferEncoding,
329 ContentEncoding,
330 AcceptEncoding,
331 };
332
333 void setHeaderMemory(Span<char> memory);
334 void setWritableStream(AsyncWritableStream& stream)
335 {
336 destinationStream = &stream;
337 writableStream = &stream;
338 }
339
340 [[nodiscard]] bool hasHeader(KnownHeader header) const;
341 [[nodiscard]] bool hasSentHeaders() const { return headersSent; }
342 [[nodiscard]] bool hasEnded() const { return endCalled; }
343 [[nodiscard]] bool isChunkedTransferEncodingEnabled() const { return chunkedTransferEncodingEnabled; }
344
345 HttpFixedBufferWriter responseHeaders;
346 Span<char> headerMemory;
347
348 bool headersSent = false;
349 bool endCalled = false;
350
351 bool forceDisableKeepAlive = false;
352 bool keepAlive = true;
353 bool connectionHeaderAdded = false;
354 bool hostHeaderAdded = false;
355 bool userAgentHeaderAdded = false;
356 bool contentLengthAdded = false;
357 bool contentTypeAdded = false;
358 bool transferEncodingAdded = false;
359 bool contentEncodingAdded = false;
360 bool acceptEncodingAdded = false;
361 bool chunkedTransferEncodingEnabled = false;
362
363 AsyncWritableStream* destinationStream = nullptr;
364 AsyncWritableStream* writableStream = nullptr;
365 ChunkedWritableStream chunkedWritableStream;
366};
367
369struct SC_HTTP_EXPORT HttpResponse : public HttpOutgoingMessage
370{
372 Result startResponse(int httpCode);
373
375 Result startResponse(int httpCode, StringSpan reasonPhrase);
376
378 Result startBody(int httpCode, uint64_t contentLength, StringSpan contentType = {});
379
382 Result sendBytes(int httpCode, Span<const char> body, StringSpan contentType = {});
383
386 Result sendBody(int httpCode, StringSpan body, StringSpan contentType = {});
387
390 Result sendText(int httpCode, StringSpan body);
391
393 Result sendEmpty(int httpCode);
394
395 private:
396 friend struct HttpConnectionsPool;
397 friend struct HttpAsyncServer;
398
400 void grabUnusedHeaderMemory(HttpRequest& request);
401};
402
404struct SC_HTTP_EXPORT HttpAsyncClientRequest : public HttpOutgoingMessage
405{
406 enum class BodyType : uint8_t
407 {
408 None,
409 Manual,
410 Span,
411 Stream,
412 Multipart,
413 };
414
415 void reset();
416
417 Result startRequest(HttpParser::Method method, StringSpan url);
418 Result setExpectedBodyLength(uint64_t value);
419 Result setBody(Span<const char> value);
420 Result setBody(StringSpan value) { return setBody(value.toCharSpan()); }
421 Result setBody(AsyncReadableStream& stream);
422 void setBody(AsyncReadableStream& stream, uint64_t contentLengthValue);
423 Result setCompressedBody(AsyncReadableStream& stream, SyncZLibTransformStream& compressor,
424 HttpContentEncoding encoding);
425 void setMultipart(HttpMultipartWriter& value);
426 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
427
428 [[nodiscard]] HttpParser::Method getMethod() const { return method; }
429
430 [[nodiscard]] StringSpan getRequestTarget() const { return url; }
431 [[nodiscard]] StringSpan getURL() const { return url; }
432 [[nodiscard]] BodyType getBodyType() const { return bodyType; }
433 [[nodiscard]] uint64_t getContentLength() const { return contentLength; }
434 [[nodiscard]] bool usesChunkedTransferEncoding() const { return chunkedTransferEncodingEnabled; }
435 [[nodiscard]] HttpContentEncoding getContentEncoding() const { return contentEncoding; }
436
437 private:
438 friend struct HttpAsyncClient;
439
440 void setDefaultHost(StringSpan value) { defaultHost = value; }
441
442 [[nodiscard]] bool hasTransferEncodingHeader() const { return hasHeader(KnownHeader::TransferEncoding); }
443 [[nodiscard]] bool hasAcceptEncodingHeader() const { return hasHeader(KnownHeader::AcceptEncoding); }
444
445 [[nodiscard]] AsyncReadableStream* getBodyStream() const { return bodyStream; }
446 [[nodiscard]] SyncZLibTransformStream* getBodyTransform() const { return bodyTransform; }
447 [[nodiscard]] const HttpMultipartWriter* getMultipartWriter() const { return multipartWriter; }
448 [[nodiscard]] Span<const char> getBodySpan() const { return bodySpan; }
449
450 HttpParser::Method method = HttpParser::Method::HttpGET;
451 StringSpan url;
452 AsyncReadableStream* bodyStream = nullptr;
453 SyncZLibTransformStream* bodyTransform = nullptr;
454 BodyType bodyType = BodyType::None;
455 Span<const char> bodySpan;
456 uint64_t contentLength = 0;
457 HttpContentEncoding contentEncoding = HttpContentEncoding::Identity;
458 HttpMultipartWriter* multipartWriter = nullptr;
459 StringSpan defaultHost;
460
461 Function<void(AsyncBufferView::ID)> userHeadersSentCallback;
462 Function<void(AsyncBufferView::ID)> internalHeadersSentCallback;
463};
464
466struct SC_HTTP_EXPORT HttpConnection : public HttpConnectionBase
467{
469
470 struct SC_HTTP_EXPORT ID
471 {
472 size_t getIndex() const { return index; }
473
474 private:
475 friend struct HttpConnectionsPool;
476 size_t index = 0;
477 };
478
480 void reset();
481
483 ID getConnectionID() const { return connectionID; }
484
486 void markWebSocketUpgraded() { webSocketUpgraded = true; }
487
489 [[nodiscard]] bool isWebSocketUpgraded() const { return webSocketUpgraded; }
490
491 HttpRequest request;
492 HttpResponse response;
493
494 uint32_t requestCount = 0;
495
496 protected:
497 enum class State
498 {
499 Inactive,
500 Active
501 };
502 friend struct HttpConnectionsPool;
503 friend struct HttpAsyncServer;
504
505 State state = State::Inactive;
506 ID connectionID;
507 bool webSocketUpgraded = false;
508};
509
511template <typename Type>
512struct SC_HTTP_EXPORT SpanWithStride
513{
515 constexpr SpanWithStride() : data(nullptr), sizeElements(0), strideInBytes(0) {}
516
521 constexpr SpanWithStride(void* data, size_t sizeInElements, size_t strideInBytes)
522 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
523 {}
524
525 template <typename U>
526 constexpr SpanWithStride(Span<U> span)
527 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
528 {}
529
530 [[nodiscard]] constexpr size_t sizeInElements() const { return sizeElements; }
531 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
532
533 template <typename U>
534 SpanWithStride<U> castTo()
535 {
536 return {static_cast<U*>(reinterpret_cast<Type*>(data)), sizeElements, strideInBytes};
537 }
538
539 [[nodiscard]] Type& operator[](size_t idx)
540 {
541 return *reinterpret_cast<Type*>(reinterpret_cast<char*>(data) + idx * strideInBytes);
542 }
543
544 [[nodiscard]] const Type& operator[](size_t idx) const
545 {
546 return *reinterpret_cast<const Type*>(reinterpret_cast<const char*>(data) + idx * strideInBytes);
547 }
548
549 private:
550 void* data;
551 size_t sizeElements;
552 size_t strideInBytes;
553};
554
556struct SC_HTTP_EXPORT HttpConnectionsPool
557{
559 {
560 size_t readQueueSize = 3;
561 size_t writeQueueSize = 3;
562 size_t buffersQueueSize = 6;
563 size_t headerBytesLength = 8 * 1024;
564 size_t streamBytesLength = 512 * 1024;
565 };
566
567 struct SC_HTTP_EXPORT Memory
568 {
571
572 Span<AsyncBufferView> allBuffers;
573
574 Span<char> allHeaders;
575 Span<char> allStreams;
576
578 };
579
582
585
587 [[nodiscard]] size_t getNumActiveConnections() const { return numConnections; }
588
590 [[nodiscard]] size_t getNumTotalConnections() const { return connections.sizeInElements(); }
591
593 [[nodiscard]] size_t getHighestActiveConnection() const { return highestActiveConnection; }
594
597 {
598 return connections[connectionID.index];
599 }
600
602 [[nodiscard]] HttpConnection& getConnectionAt(size_t idx) { return connections[idx]; }
603
605 [[nodiscard]] bool activateNew(HttpConnection::ID& connectionID);
606
608 [[nodiscard]] bool deactivate(HttpConnection::ID connectionID);
609
610 private:
612
613 size_t numConnections = 0;
614
615 // Optimization for HttpAsyncServer::resize to avoid having to scan all connections
616 size_t highestActiveConnection = 0;
617};
618
620template <int ReadQueue, int WriteQueue, int HeaderBytes, int StreamBytes, int ExtraBuffers, typename BaseClass>
621struct SC_HTTP_EXPORT HttpStaticConnection : public BaseClass
622{
623 AsyncReadableStream::Request readQueue[ReadQueue];
624 AsyncWritableStream::Request writeQueue[WriteQueue];
625
626 AsyncBufferView buffers[ReadQueue + WriteQueue + ExtraBuffers];
627
628 char headerStorage[HeaderBytes];
629 char streamStorage[StreamBytes];
630
631 constexpr HttpStaticConnection()
632 {
633 constexpr const size_t NumSlices = ReadQueue;
634 constexpr const size_t SliceLength = StreamBytes / NumSlices;
635
636 Span<char> memory = streamStorage;
637 for (size_t idx = 0; idx < NumSlices; ++idx)
638 {
639 Span<char> slice;
640 (void)memory.sliceStartLength(idx * SliceLength, SliceLength, slice);
641 buffers[idx] = slice;
642 buffers[idx].setReusable(true);
643 }
644 this->setHeaderMemory(headerStorage);
645 this->buffersPool.setBuffers(buffers);
646 this->readableSocketStream.setReadQueue(readQueue);
647 this->writableSocketStream.setWriteQueue(writeQueue);
648 }
649};
650
652} // namespace SC
struct SC_FOUNDATION_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:27
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:33
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
Definition AsyncStreams.h:58
A Span of bytes memory to be read or written by async streams.
Definition AsyncStreams.h:56
void setReusable(bool reusable)
Tags this AsyncBufferView as reusable after its refCount goes to zero.
Definition AsyncStreams.h:97
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:169
void setBuffers(Span< AsyncBufferView > newBuffers)
Sets memory for the new buffers.
Definition AsyncStreams.h:199
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:550
Definition AsyncStreams.h:225
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:220
Definition AsyncStreams.h:363
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:356
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:405
Incoming HTTP response received by the client.
Definition HttpConnection.h:246
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:49
Async Http Server.
Definition HttpAsyncServer.h:40
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:73
Definition HttpConnection.h:471
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:467
bool isWebSocketUpgraded() const
Returns true after the HTTP layer handed this connection to WebSocket code.
Definition HttpConnection.h:489
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:486
ID getConnectionID() const
The ID used to find this client in HttpConnectionsPool.
Definition HttpConnection.h:483
Definition HttpConnection.h:559
Definition HttpConnection.h:568
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:557
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:587
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:593
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:602
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:596
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:590
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:97
Incoming message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:95
bool getKeepAlive() const
Gets whether the other party requested the connection to stay alive.
Definition HttpConnection.h:120
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:114
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:132
uint64_t getBodyBytesRemaining() const
Returns how many body bytes are still expected for this message.
Definition HttpConnection.h:129
bool hasReceivedHeaders() const
Returns true once the incoming message headers have been parsed.
Definition HttpConnection.h:117
HttpBodyFramingKind getBodyFramingKind() const
Returns the effective framing mode for the incoming body.
Definition HttpConnection.h:126
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:260
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:258
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:318
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:309
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:220
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:225
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:222
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:370
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 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:622
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
Low-level OS socket handle.
Definition Socket.h:159
View over a contiguous sequence of items with a custom stride between elements.
Definition HttpConnection.h:513
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:521
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:515
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition Span.h:121
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37
Span< const char > toCharSpan() const
Obtain a const char Span from this StringView.
Definition StringSpan.h:82
Definition ZLibTransformStreams.h:11