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 "../Common/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
47 Span<const char> body;
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 setTransportStreams(AsyncReadableStream& readable, AsyncWritableStream& writable);
88 void resetTransportStreams();
89
90 [[nodiscard]] AsyncReadableStream& getReadableTransportStream() { return *readableTransportStream; }
91 [[nodiscard]] AsyncWritableStream& getWritableTransportStream() { return *writableTransportStream; }
92
93 [[nodiscard]] const AsyncReadableStream& getReadableTransportStream() const { return *readableTransportStream; }
94 [[nodiscard]] const AsyncWritableStream& getWritableTransportStream() const { return *writableTransportStream; }
95
96 void reset();
97
98 protected:
99 Span<char> headerMemory;
100
101 private:
102 AsyncReadableStream* readableTransportStream = &readableSocketStream;
103 AsyncWritableStream* writableTransportStream = &writableSocketStream;
104};
105
107struct SC_HTTP_EXPORT HttpIncomingMessage
108{
109 struct SC_HTTP_EXPORT BodyStream : public AsyncReadableStream
110 {
111 BodyStream();
112
113 Result begin(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
114 bool pushBodyData(AsyncBufferView::ID bufferID, size_t sizeInBytes);
115 void finishBody();
116 void failBody(Result result);
117
118 Function<Result()> onReadRequest;
119 Request queue[4];
120
121 private:
122 virtual Result asyncRead() override;
123 virtual Result asyncResumeReading() override;
124 };
125
127 const HttpParser& getParser() const { return parsedHeaders.parser; }
128
130 [[nodiscard]] bool hasReceivedHeaders() const { return parsedHeaders.headersEndReceived; }
131
133 [[nodiscard]] bool getKeepAlive() const { return parsedHeaders.parser.connectionKeepAlive; }
134
136 [[nodiscard]] StringSpan getVersion() const;
137
139 [[nodiscard]] HttpBodyFramingKind getBodyFramingKind() const { return bodyFramingKind; }
140
142 [[nodiscard]] uint64_t getBodyBytesRemaining() const { return bodyBytesRemaining; }
143
145 [[nodiscard]] bool isBodyComplete() const { return bodyComplete; }
146
148 [[nodiscard]] bool isMultipart() const;
149
151 [[nodiscard]] StringSpan getBoundary() const;
152
157 [[nodiscard]] bool getHeader(StringSpan headerName, StringSpan& value) const;
158
161
164
166 Result consumeBodyBytes(size_t bytes);
167
168 protected:
169 void resetIncoming(HttpParser::Type type, Span<char> memory);
170
171 [[nodiscard]] Span<char> getUnusedHeaderMemory() const { return parsedHeaders.availableHeader; }
172
173 Result initBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
174 Result startBodyStream();
175 bool pushBodyData(AsyncBufferView::ID bufferID, size_t sizeInBytes);
176 void finishBodyStream();
177 void failBodyStream(Result result);
178 void abortBodyStream();
179 Result prepareBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest,
180 bool allowCloseDelimited);
181 Result processBodyData(AsyncReadableStream& sourceStream, AsyncBufferView::ID bufferID, Span<const char> readData,
182 bool allowTrailingData);
183
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; }
188
193 [[nodiscard]] bool findParserToken(HttpParser::Token token, StringSpan& res) const;
194
197 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
198 AsyncBufferView::ID bufferID, bool stopAtHeadersEnd, bool unshiftPendingBodyToStream = true);
199
201 [[nodiscard]] size_t getHeadersLength() const;
202
203 enum class ChunkedState : uint8_t
204 {
205 Size,
206 SizeExtension,
207 SizeLF,
208 Data,
209 DataCR,
210 DataLF,
211 TrailerLineStart,
212 TrailerEndLF,
213 Finished,
214 };
215
216 HttpParsedHeaders parsedHeaders;
217 Span<char> headerMemory;
218 AsyncReadableStream* readableStream = nullptr;
219 uint64_t bodyBytesRemaining = 0;
220 HttpBodyFramingKind bodyFramingKind = HttpBodyFramingKind::None;
221 bool bodyComplete = true;
222 bool bodyStreamStarted = false;
223 BodyStream bodyStream;
224 ChunkedState chunkedState = ChunkedState::Size;
225 uint64_t chunkedChunkSize = 0;
226 uint64_t chunkedBytesRemaining = 0;
227 bool chunkedSizeHasDigits = false;
228};
229
231struct SC_HTTP_EXPORT HttpRequest : public HttpIncomingMessage
232{
234 StringSpan getRequestTarget() const { return url; }
235
237 StringSpan getURL() const { return url; }
238
240 void reset();
241
242 private:
243 friend struct HttpConnectionsPool;
244 friend struct HttpResponse;
245 friend struct HttpAsyncServer;
246
247 void setHeaderMemory(Span<char> memory);
248
250 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
251 AsyncBufferView::ID bufferID);
252
253 StringSpan url;
254};
255
257struct SC_HTTP_EXPORT HttpAsyncClientResponse : public HttpIncomingMessage
258{
259 private:
260 friend struct HttpAsyncClient;
261
262 void reset(Span<char> memory);
263 Result writeHeaders(uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
264 AsyncBufferView::ID bufferID);
265 BodyStream& rawBodyStream() { return bodyStream; }
266};
267
269struct SC_HTTP_EXPORT HttpOutgoingMessage
270{
271 struct SC_HTTP_EXPORT ChunkedWritableStream : public AsyncWritableStream
272 {
274
275 Result init(AsyncBuffersPool& buffersPool, AsyncWritableStream& destination);
276
277 protected:
278 virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function<void(AsyncBufferView::ID)> cb) override;
279 virtual bool canEndWritable() override;
280
281 private:
282 void onChunkHeaderWritten(AsyncBufferView::ID);
283 void onChunkBodyWritten(AsyncBufferView::ID);
284 void onChunkTerminatorWritten(AsyncBufferView::ID);
285 void onFinalChunkWritten(AsyncBufferView::ID);
286
287 AsyncWritableStream* destination = nullptr;
288
289 AsyncBufferView::ID currentBodyBufferID;
290 Function<void(AsyncBufferView::ID)> currentBodyCallback;
291
292 bool finalChunkStarted = false;
293 bool finalChunkWritten = false;
294
295 char headerStorage[20] = {0};
296
297 Request queue[4];
298 };
299
303 Result addHeader(StringSpan headerName, StringSpan headerValue);
304
306 Result addContentLength(uint64_t value);
307
310
312 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
313
315 void reset();
316
318 Result end();
319
321 AsyncWritableStream& getWritableStream() { return *writableStream; }
322
326 void setKeepAlive(bool keepAlive);
327
330 [[nodiscard]] bool getKeepAlive() const { return forceDisableKeepAlive ? false : keepAlive; }
331
332 protected:
333 enum class KnownHeader : uint8_t
334 {
335 Connection,
336 Host,
337 UserAgent,
338 ContentLength,
339 ContentType,
340 TransferEncoding,
341 ContentEncoding,
342 AcceptEncoding,
343 };
344
345 void setHeaderMemory(Span<char> memory);
346 void setWritableStream(AsyncWritableStream& stream)
347 {
348 destinationStream = &stream;
349 writableStream = &stream;
350 }
351
352 [[nodiscard]] bool hasHeader(KnownHeader header) const;
353 [[nodiscard]] bool hasSentHeaders() const { return headersSent; }
354 [[nodiscard]] bool hasEnded() const { return endCalled; }
355 [[nodiscard]] bool isChunkedTransferEncodingEnabled() const { return chunkedTransferEncodingEnabled; }
356
357 HttpFixedBufferWriter responseHeaders;
358 Span<char> headerMemory;
359
360 bool headersSent = false;
361 bool endCalled = false;
362
363 bool forceDisableKeepAlive = false;
364 bool keepAlive = true;
365 bool connectionHeaderAdded = false;
366 bool hostHeaderAdded = false;
367 bool userAgentHeaderAdded = false;
368 bool contentLengthAdded = false;
369 bool contentTypeAdded = false;
370 bool transferEncodingAdded = false;
371 bool contentEncodingAdded = false;
372 bool acceptEncodingAdded = false;
373 bool chunkedTransferEncodingEnabled = false;
374
375 AsyncWritableStream* destinationStream = nullptr;
376 AsyncWritableStream* writableStream = nullptr;
377 ChunkedWritableStream chunkedWritableStream;
378};
379
381struct SC_HTTP_EXPORT HttpResponse : public HttpOutgoingMessage
382{
384 Result startResponse(int httpCode);
385
387 Result startResponse(int httpCode, StringSpan reasonPhrase);
388
390 Result startBody(int httpCode, uint64_t contentLength, StringSpan contentType = {});
391
394 Result sendBytes(int httpCode, Span<const char> body, StringSpan contentType = {});
395
398 Result sendBody(int httpCode, StringSpan body, StringSpan contentType = {});
399
402 Result sendText(int httpCode, StringSpan body);
403
406 Result sendJson(int httpCode, StringSpan body);
407
409 Result sendEmpty(int httpCode);
410
412 Result sendMethodNotAllowed(StringSpan allow);
413
415 Result sendRedirect(int httpCode, StringSpan location);
416
417 private:
418 friend struct HttpConnectionsPool;
419 friend struct HttpAsyncServer;
420
422 void grabUnusedHeaderMemory(HttpRequest& request);
423};
424
426struct SC_HTTP_EXPORT HttpAsyncClientRequest : public HttpOutgoingMessage
427{
428 enum class BodyType : uint8_t
429 {
430 None,
431 Manual,
432 Span,
433 Stream,
434 Multipart,
435 };
436
437 void reset();
438
439 Result startRequest(HttpParser::Method method, StringSpan url);
440 Result setExpectedBodyLength(uint64_t value);
441 Result setBody(Span<const char> value);
442 Result setBody(StringSpan value) { return setBody(value.toCharSpan()); }
443 Result setBody(AsyncReadableStream& stream);
444 void setBody(AsyncReadableStream& stream, uint64_t contentLengthValue);
445 Result setCompressedBody(AsyncReadableStream& stream, SyncZLibTransformStream& compressor,
446 HttpContentEncoding encoding);
447 void setMultipart(HttpMultipartWriter& value);
448 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
449
450 [[nodiscard]] HttpParser::Method getMethod() const { return method; }
451
452 [[nodiscard]] StringSpan getRequestTarget() const { return url; }
453 [[nodiscard]] StringSpan getURL() const { return url; }
454 [[nodiscard]] BodyType getBodyType() const { return bodyType; }
455 [[nodiscard]] uint64_t getContentLength() const { return contentLength; }
456 [[nodiscard]] bool usesChunkedTransferEncoding() const { return chunkedTransferEncodingEnabled; }
457 [[nodiscard]] HttpContentEncoding getContentEncoding() const { return contentEncoding; }
458
459 private:
460 friend struct HttpAsyncClient;
461
462 void setDefaultHost(StringSpan value) { defaultHost = value; }
463
464 [[nodiscard]] bool hasTransferEncodingHeader() const { return hasHeader(KnownHeader::TransferEncoding); }
465 [[nodiscard]] bool hasAcceptEncodingHeader() const { return hasHeader(KnownHeader::AcceptEncoding); }
466
467 [[nodiscard]] AsyncReadableStream* getBodyStream() const { return bodyStream; }
468 [[nodiscard]] SyncZLibTransformStream* getBodyTransform() const { return bodyTransform; }
469 [[nodiscard]] const HttpMultipartWriter* getMultipartWriter() const { return multipartWriter; }
470 [[nodiscard]] Span<const char> getBodySpan() const { return bodySpan; }
471
472 HttpParser::Method method = HttpParser::Method::HttpGET;
473 StringSpan url;
474 AsyncReadableStream* bodyStream = nullptr;
475 SyncZLibTransformStream* bodyTransform = nullptr;
476 BodyType bodyType = BodyType::None;
477 Span<const char> bodySpan;
478 uint64_t contentLength = 0;
479 HttpContentEncoding contentEncoding = HttpContentEncoding::Identity;
480 HttpMultipartWriter* multipartWriter = nullptr;
481 StringSpan defaultHost;
482
483 Function<void(AsyncBufferView::ID)> userHeadersSentCallback;
484 Function<void(AsyncBufferView::ID)> internalHeadersSentCallback;
485};
486
488struct SC_HTTP_EXPORT HttpConnection : public HttpConnectionBase
489{
491
492 struct SC_HTTP_EXPORT ID
493 {
494 size_t getIndex() const { return index; }
495
496 private:
497 friend struct HttpConnectionsPool;
498 size_t index = 0;
499 };
500
502 void reset();
503
505 ID getConnectionID() const { return connectionID; }
506
508 void markWebSocketUpgraded() { webSocketUpgraded = true; }
509
511 [[nodiscard]] bool isWebSocketUpgraded() const { return webSocketUpgraded; }
512
514 Result sendBodyCopy(int httpCode, StringSpan body, StringSpan contentType = {});
515
517 Result sendTextCopy(int httpCode, StringSpan body);
518
520 Result sendJsonCopy(int httpCode, StringSpan body);
521
522 HttpRequest request;
523 HttpResponse response;
524
525 uint32_t requestCount = 0;
526
527 protected:
528 enum class State
529 {
530 Inactive,
531 Active
532 };
533 friend struct HttpConnectionsPool;
534 friend struct HttpAsyncServer;
535
536 State state = State::Inactive;
537 ID connectionID;
538 bool webSocketUpgraded = false;
539};
540
542template <typename Type>
543struct SC_HTTP_EXPORT SpanWithStride
544{
546 constexpr SpanWithStride() : data(nullptr), sizeElements(0), strideInBytes(0) {}
547
552 constexpr SpanWithStride(void* data, size_t sizeInElements, size_t strideInBytes)
553 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
554 {}
555
556 template <typename U>
557 constexpr SpanWithStride(Span<U> span)
558 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
559 {}
560
561 [[nodiscard]] constexpr size_t sizeInElements() const { return sizeElements; }
562 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
563
564 template <typename U>
565 SpanWithStride<U> castTo()
566 {
567 return {static_cast<U*>(reinterpret_cast<Type*>(data)), sizeElements, strideInBytes};
568 }
569
570 [[nodiscard]] Type& operator[](size_t idx)
571 {
572 return *reinterpret_cast<Type*>(reinterpret_cast<char*>(data) + idx * strideInBytes);
573 }
574
575 [[nodiscard]] const Type& operator[](size_t idx) const
576 {
577 return *reinterpret_cast<const Type*>(reinterpret_cast<const char*>(data) + idx * strideInBytes);
578 }
579
580 private:
581 void* data;
582 size_t sizeElements;
583 size_t strideInBytes;
584};
585
587struct SC_HTTP_EXPORT HttpConnectionsPool
588{
590 {
591 size_t readQueueSize = 3;
592 size_t writeQueueSize = 3;
593 size_t buffersQueueSize = 6;
594 size_t headerBytesLength = 8 * 1024;
595 size_t streamBytesLength = 512 * 1024;
596 };
597
598 struct SC_HTTP_EXPORT Memory
599 {
600 Span<AsyncReadableStream::Request> allReadQueue;
601 Span<AsyncWritableStream::Request> allWriteQueue;
602
603 Span<AsyncBufferView> allBuffers;
604
605 Span<char> allHeaders;
606 Span<char> allStreams;
607
609 };
610
612 Result init(SpanWithStride<HttpConnection> connectionsStorage);
613
615 Result close();
616
618 [[nodiscard]] size_t getNumActiveConnections() const { return numConnections; }
619
621 [[nodiscard]] size_t getNumTotalConnections() const { return connections.sizeInElements(); }
622
624 [[nodiscard]] size_t getHighestActiveConnection() const { return highestActiveConnection; }
625
628 {
629 return connections[connectionID.index];
630 }
631
633 [[nodiscard]] HttpConnection& getConnectionAt(size_t idx) { return connections[idx]; }
634
636 [[nodiscard]] bool activateNew(HttpConnection::ID& connectionID);
637
639 [[nodiscard]] bool activate(HttpConnection& connection, HttpConnection::ID& connectionID);
640
642 [[nodiscard]] bool deactivate(HttpConnection::ID connectionID);
643
644 private:
646
647 size_t numConnections = 0;
648
649 // Optimization for HttpAsyncServer::resize to avoid having to scan all connections
650 size_t highestActiveConnection = 0;
651};
652
654template <int ReadQueue, int WriteQueue, int HeaderBytes, int StreamBytes, int ExtraBuffers, typename BaseClass>
655struct SC_HTTP_EXPORT HttpStaticConnection : public BaseClass
656{
657 AsyncReadableStream::Request readQueue[ReadQueue];
658 AsyncWritableStream::Request writeQueue[WriteQueue];
659
660 AsyncBufferView buffers[ReadQueue + WriteQueue + ExtraBuffers];
661
662 char headerStorage[HeaderBytes];
663 char streamStorage[StreamBytes];
664
665 constexpr HttpStaticConnection()
666 {
667 constexpr const size_t NumSlices = ReadQueue;
668 constexpr const size_t SliceLength = StreamBytes / NumSlices;
669
670 Span<char> memory = streamStorage;
671 for (size_t idx = 0; idx < NumSlices; ++idx)
672 {
673 Span<char> slice;
674 (void)memory.sliceStartLength(idx * SliceLength, SliceLength, slice);
675 buffers[idx] = slice;
676 buffers[idx].setReusable(true);
677 }
678 this->setHeaderMemory(headerStorage);
679 this->buffersPool.setBuffers(buffers);
680 this->readableSocketStream.setReadQueue(readQueue);
681 this->writableSocketStream.setWriteQueue(writeQueue);
682 }
683};
684
686} // namespace SC
Definition AsyncStreams.h:67
A Span of bytes memory to be read or written by async streams.
Definition AsyncStreams.h:65
void setReusable(bool reusable)
Tags this AsyncBufferView as reusable after its refCount goes to zero.
Definition AsyncStreams.h:106
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:178
void setBuffers(Span< AsyncBufferView > newBuffers)
Sets memory for the new buffers.
Definition AsyncStreams.h:208
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:561
Definition AsyncStreams.h:234
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:229
Definition AsyncStreams.h:372
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:365
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:427
Incoming HTTP response received by the client.
Definition HttpConnection.h:258
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:85
Async Http Server.
Definition HttpAsyncServer.h:54
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:73
Definition HttpConnection.h:493
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:489
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:511
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:508
ID getConnectionID() const
The ID used to find this client in HttpConnectionsPool.
Definition HttpConnection.h:505
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:590
Definition HttpConnection.h:599
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:588
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:618
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:624
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:633
bool activate(HttpConnection &connection, HttpConnection::ID &connectionID)
Activates a specific inactive connection owned by this pool.
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:627
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:621
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
Result writeHeaders(const uint32_t maxHeaderSize, Span< const char > readData, AsyncReadableStream &stream, AsyncBufferView::ID bufferID, bool stopAtHeadersEnd, bool unshiftPendingBodyToStream=true)
Parses an incoming slice of data eventually copying it to the availableHeader.
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
Definition HttpConnection.h:42
Definition HttpConnection.h:40
Definition HttpConnection.h:272
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:270
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:330
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:321
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:232
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:237
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:234
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:382
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:656
Low-level OS socket handle.
Definition Socket.h:207
View over a contiguous sequence of items with a custom stride between elements.
Definition HttpConnection.h:544
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:552
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:546
Definition ZLibTransformStreams.h:10