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, const char* outOfSpaceError, const char* sizeExceededError,
199 bool stopAtHeadersEnd, bool unshiftPendingBodyToStream = true);
200
202 [[nodiscard]] size_t getHeadersLength() const;
203
204 enum class ChunkedState : uint8_t
205 {
206 Size,
207 SizeExtension,
208 SizeLF,
209 Data,
210 DataCR,
211 DataLF,
212 TrailerLineStart,
213 TrailerEndLF,
214 Finished,
215 };
216
217 HttpParsedHeaders parsedHeaders;
218 Span<char> headerMemory;
219 AsyncReadableStream* readableStream = nullptr;
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;
229};
230
232struct SC_HTTP_EXPORT HttpRequest : public HttpIncomingMessage
233{
235 StringSpan getRequestTarget() const { return url; }
236
238 StringSpan getURL() const { return url; }
239
241 void reset();
242
243 private:
244 friend struct HttpConnectionsPool;
245 friend struct HttpResponse;
246 friend struct HttpAsyncServer;
247
248 void setHeaderMemory(Span<char> memory);
249
251 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
252 AsyncBufferView::ID bufferID);
253
254 StringSpan url;
255};
256
258struct SC_HTTP_EXPORT HttpAsyncClientResponse : public HttpIncomingMessage
259{
260 private:
261 friend struct HttpAsyncClient;
262
263 void reset(Span<char> memory);
264 Result writeHeaders(uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
265 AsyncBufferView::ID bufferID);
266 BodyStream& rawBodyStream() { return bodyStream; }
267};
268
270struct SC_HTTP_EXPORT HttpOutgoingMessage
271{
272 struct SC_HTTP_EXPORT ChunkedWritableStream : public AsyncWritableStream
273 {
275
276 Result init(AsyncBuffersPool& buffersPool, AsyncWritableStream& destination);
277
278 protected:
279 virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function<void(AsyncBufferView::ID)> cb) override;
280 virtual bool canEndWritable() override;
281
282 private:
283 void onChunkHeaderWritten(AsyncBufferView::ID);
284 void onChunkBodyWritten(AsyncBufferView::ID);
285 void onChunkTerminatorWritten(AsyncBufferView::ID);
286 void onFinalChunkWritten(AsyncBufferView::ID);
287
288 AsyncWritableStream* destination = nullptr;
289
290 AsyncBufferView::ID currentBodyBufferID;
291 Function<void(AsyncBufferView::ID)> currentBodyCallback;
292
293 bool finalChunkStarted = false;
294 bool finalChunkWritten = false;
295
296 char headerStorage[20] = {0};
297
298 Request queue[4];
299 };
300
304 Result addHeader(StringSpan headerName, StringSpan headerValue);
305
307 Result addContentLength(uint64_t value);
308
311
313 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
314
316 void reset();
317
319 Result end();
320
322 AsyncWritableStream& getWritableStream() { return *writableStream; }
323
327 void setKeepAlive(bool keepAlive);
328
331 [[nodiscard]] bool getKeepAlive() const { return forceDisableKeepAlive ? false : keepAlive; }
332
333 protected:
334 enum class KnownHeader : uint8_t
335 {
336 Connection,
337 Host,
338 UserAgent,
339 ContentLength,
340 ContentType,
341 TransferEncoding,
342 ContentEncoding,
343 AcceptEncoding,
344 };
345
346 void setHeaderMemory(Span<char> memory);
347 void setWritableStream(AsyncWritableStream& stream)
348 {
349 destinationStream = &stream;
350 writableStream = &stream;
351 }
352
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; }
357
358 HttpFixedBufferWriter responseHeaders;
359 Span<char> headerMemory;
360
361 bool headersSent = false;
362 bool endCalled = false;
363
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;
375
376 AsyncWritableStream* destinationStream = nullptr;
377 AsyncWritableStream* writableStream = nullptr;
378 ChunkedWritableStream chunkedWritableStream;
379};
380
382struct SC_HTTP_EXPORT HttpResponse : public HttpOutgoingMessage
383{
385 Result startResponse(int httpCode);
386
388 Result startResponse(int httpCode, StringSpan reasonPhrase);
389
391 Result startBody(int httpCode, uint64_t contentLength, StringSpan contentType = {});
392
395 Result sendBytes(int httpCode, Span<const char> body, StringSpan contentType = {});
396
399 Result sendBody(int httpCode, StringSpan body, StringSpan contentType = {});
400
403 Result sendText(int httpCode, StringSpan body);
404
407 Result sendJson(int httpCode, StringSpan body);
408
410 Result sendEmpty(int httpCode);
411
413 Result sendMethodNotAllowed(StringSpan allow);
414
416 Result sendRedirect(int httpCode, StringSpan location);
417
418 private:
419 friend struct HttpConnectionsPool;
420 friend struct HttpAsyncServer;
421
423 void grabUnusedHeaderMemory(HttpRequest& request);
424};
425
427struct SC_HTTP_EXPORT HttpAsyncClientRequest : public HttpOutgoingMessage
428{
429 enum class BodyType : uint8_t
430 {
431 None,
432 Manual,
433 Span,
434 Stream,
435 Multipart,
436 };
437
438 void reset();
439
440 Result startRequest(HttpParser::Method method, StringSpan url);
441 Result setExpectedBodyLength(uint64_t value);
442 Result setBody(Span<const char> value);
443 Result setBody(StringSpan value) { return setBody(value.toCharSpan()); }
444 Result setBody(AsyncReadableStream& stream);
445 void setBody(AsyncReadableStream& stream, uint64_t contentLengthValue);
446 Result setCompressedBody(AsyncReadableStream& stream, SyncZLibTransformStream& compressor,
447 HttpContentEncoding encoding);
448 void setMultipart(HttpMultipartWriter& value);
449 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
450
451 [[nodiscard]] HttpParser::Method getMethod() const { return method; }
452
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; }
459
460 private:
461 friend struct HttpAsyncClient;
462
463 void setDefaultHost(StringSpan value) { defaultHost = value; }
464
465 [[nodiscard]] bool hasTransferEncodingHeader() const { return hasHeader(KnownHeader::TransferEncoding); }
466 [[nodiscard]] bool hasAcceptEncodingHeader() const { return hasHeader(KnownHeader::AcceptEncoding); }
467
468 [[nodiscard]] AsyncReadableStream* getBodyStream() const { return bodyStream; }
469 [[nodiscard]] SyncZLibTransformStream* getBodyTransform() const { return bodyTransform; }
470 [[nodiscard]] const HttpMultipartWriter* getMultipartWriter() const { return multipartWriter; }
471 [[nodiscard]] Span<const char> getBodySpan() const { return bodySpan; }
472
473 HttpParser::Method method = HttpParser::Method::HttpGET;
474 StringSpan url;
475 AsyncReadableStream* bodyStream = nullptr;
476 SyncZLibTransformStream* bodyTransform = nullptr;
477 BodyType bodyType = BodyType::None;
478 Span<const char> bodySpan;
479 uint64_t contentLength = 0;
480 HttpContentEncoding contentEncoding = HttpContentEncoding::Identity;
481 HttpMultipartWriter* multipartWriter = nullptr;
482 StringSpan defaultHost;
483
484 Function<void(AsyncBufferView::ID)> userHeadersSentCallback;
485 Function<void(AsyncBufferView::ID)> internalHeadersSentCallback;
486};
487
489struct SC_HTTP_EXPORT HttpConnection : public HttpConnectionBase
490{
492
493 struct SC_HTTP_EXPORT ID
494 {
495 size_t getIndex() const { return index; }
496
497 private:
498 friend struct HttpConnectionsPool;
499 size_t index = 0;
500 };
501
503 void reset();
504
506 ID getConnectionID() const { return connectionID; }
507
509 void markWebSocketUpgraded() { webSocketUpgraded = true; }
510
512 [[nodiscard]] bool isWebSocketUpgraded() const { return webSocketUpgraded; }
513
515 Result sendBodyCopy(int httpCode, StringSpan body, StringSpan contentType = {});
516
518 Result sendTextCopy(int httpCode, StringSpan body);
519
521 Result sendJsonCopy(int httpCode, StringSpan body);
522
523 HttpRequest request;
524 HttpResponse response;
525
526 uint32_t requestCount = 0;
527
528 protected:
529 enum class State
530 {
531 Inactive,
532 Active
533 };
534 friend struct HttpConnectionsPool;
535 friend struct HttpAsyncServer;
536
537 State state = State::Inactive;
538 ID connectionID;
539 bool webSocketUpgraded = false;
540};
541
543template <typename Type>
544struct SC_HTTP_EXPORT SpanWithStride
545{
547 constexpr SpanWithStride() : data(nullptr), sizeElements(0), strideInBytes(0) {}
548
553 constexpr SpanWithStride(void* data, size_t sizeInElements, size_t strideInBytes)
554 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
555 {}
556
557 template <typename U>
558 constexpr SpanWithStride(Span<U> span)
559 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
560 {}
561
562 [[nodiscard]] constexpr size_t sizeInElements() const { return sizeElements; }
563 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
564
565 template <typename U>
566 SpanWithStride<U> castTo()
567 {
568 return {static_cast<U*>(reinterpret_cast<Type*>(data)), sizeElements, strideInBytes};
569 }
570
571 [[nodiscard]] Type& operator[](size_t idx)
572 {
573 return *reinterpret_cast<Type*>(reinterpret_cast<char*>(data) + idx * strideInBytes);
574 }
575
576 [[nodiscard]] const Type& operator[](size_t idx) const
577 {
578 return *reinterpret_cast<const Type*>(reinterpret_cast<const char*>(data) + idx * strideInBytes);
579 }
580
581 private:
582 void* data;
583 size_t sizeElements;
584 size_t strideInBytes;
585};
586
588struct SC_HTTP_EXPORT HttpConnectionsPool
589{
591 {
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;
597 };
598
599 struct SC_HTTP_EXPORT Memory
600 {
601 Span<AsyncReadableStream::Request> allReadQueue;
602 Span<AsyncWritableStream::Request> allWriteQueue;
603
604 Span<AsyncBufferView> allBuffers;
605
606 Span<char> allHeaders;
607 Span<char> allStreams;
608
610 };
611
613 Result init(SpanWithStride<HttpConnection> connectionsStorage);
614
616 Result close();
617
619 [[nodiscard]] size_t getNumActiveConnections() const { return numConnections; }
620
622 [[nodiscard]] size_t getNumTotalConnections() const { return connections.sizeInElements(); }
623
625 [[nodiscard]] size_t getHighestActiveConnection() const { return highestActiveConnection; }
626
629 {
630 return connections[connectionID.index];
631 }
632
634 [[nodiscard]] HttpConnection& getConnectionAt(size_t idx) { return connections[idx]; }
635
637 [[nodiscard]] bool activateNew(HttpConnection::ID& connectionID);
638
640 [[nodiscard]] bool deactivate(HttpConnection::ID connectionID);
641
642 private:
644
645 size_t numConnections = 0;
646
647 // Optimization for HttpAsyncServer::resize to avoid having to scan all connections
648 size_t highestActiveConnection = 0;
649};
650
652template <int ReadQueue, int WriteQueue, int HeaderBytes, int StreamBytes, int ExtraBuffers, typename BaseClass>
653struct SC_HTTP_EXPORT HttpStaticConnection : public BaseClass
654{
655 AsyncReadableStream::Request readQueue[ReadQueue];
656 AsyncWritableStream::Request writeQueue[WriteQueue];
657
658 AsyncBufferView buffers[ReadQueue + WriteQueue + ExtraBuffers];
659
660 char headerStorage[HeaderBytes];
661 char streamStorage[StreamBytes];
662
663 constexpr HttpStaticConnection()
664 {
665 constexpr const size_t NumSlices = ReadQueue;
666 constexpr const size_t SliceLength = StreamBytes / NumSlices;
667
668 Span<char> memory = streamStorage;
669 for (size_t idx = 0; idx < NumSlices; ++idx)
670 {
671 Span<char> slice;
672 (void)memory.sliceStartLength(idx * SliceLength, SliceLength, slice);
673 buffers[idx] = slice;
674 buffers[idx].setReusable(true);
675 }
676 this->setHeaderMemory(headerStorage);
677 this->buffersPool.setBuffers(buffers);
678 this->readableSocketStream.setReadQueue(readQueue);
679 this->writableSocketStream.setWriteQueue(writeQueue);
680 }
681};
682
684} // namespace SC
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
Definition ZLibTransformStreams.h:10