1 /* 2 * Copyright 2022 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #ifndef _B_HTTP_PARSER_H_ 7 #define _B_HTTP_PARSER_H_ 8 9 10 #include <functional> 11 #include <optional> 12 13 #include <HttpResult.h> 14 15 #include "HttpBuffer.h" 16 17 class BMallocIO; 18 19 namespace BPrivate { 20 21 namespace Network { 22 23 using HttpTransferFunction = std::function<size_t(const std::byte*, size_t)>; 24 25 26 enum class HttpInputStreamState { StatusLine, Fields, Body, Done }; 27 28 29 enum class HttpBodyType { NoContent, Chunked, FixedSize, VariableSize }; 30 31 32 struct BodyParseResult { 33 size_t bytesParsed; 34 size_t bytesWritten; 35 bool complete; 36 }; 37 38 39 class HttpBodyParser; 40 41 42 class HttpParser 43 { 44 public: HttpParser()45 HttpParser(){}; 46 47 // Explicitly mark request as having no content 48 void SetNoContent() noexcept; 49 50 // Parse data from response 51 bool ParseStatus(HttpBuffer& buffer, BHttpStatus& status); 52 bool ParseFields(HttpBuffer& buffer, BHttpFields& fields); 53 size_t ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 54 bool readEnd); State()55 HttpInputStreamState State() const noexcept { return fStreamState; } 56 57 // Details on the body status 58 bool HasContent() const noexcept; 59 std::optional<off_t> BodyBytesTotal() const noexcept; 60 off_t BodyBytesTransferred() const noexcept; 61 bool Complete() const noexcept; 62 63 private: 64 off_t fHeaderBytes = 0; 65 BHttpStatus fStatus; 66 HttpInputStreamState fStreamState = HttpInputStreamState::StatusLine; 67 68 // Body 69 HttpBodyType fBodyType = HttpBodyType::VariableSize; 70 std::unique_ptr<HttpBodyParser> fBodyParser = nullptr; 71 }; 72 73 74 class HttpBodyParser 75 { 76 public: 77 virtual BodyParseResult ParseBody(HttpBuffer& buffer, 78 HttpTransferFunction writeToBody, bool readEnd) = 0; 79 80 virtual std::optional<off_t> TotalBodySize() const noexcept; 81 82 off_t TransferredBodySize() const noexcept; 83 84 protected: 85 off_t fTransferredBodySize = 0; 86 }; 87 88 89 class HttpRawBodyParser : public HttpBodyParser 90 { 91 public: 92 HttpRawBodyParser(); 93 HttpRawBodyParser(off_t bodyBytesTotal); 94 virtual BodyParseResult ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 95 bool readEnd) override; 96 virtual std::optional<off_t> TotalBodySize() const noexcept override; 97 98 private: 99 std::optional<off_t> fBodyBytesTotal; 100 }; 101 102 103 class HttpChunkedBodyParser : public HttpBodyParser 104 { 105 public: 106 virtual BodyParseResult ParseBody( 107 HttpBuffer& buffer, HttpTransferFunction writeToBody, bool readEnd) override; 108 109 private: 110 enum { ChunkSize, ChunkEnd, Chunk, Trailers, Complete } fChunkParserState = ChunkSize; 111 off_t fRemainingChunkSize = 0; 112 bool fLastChunk = false; 113 }; 114 115 116 class HttpBodyDecompression : public HttpBodyParser 117 { 118 public: 119 HttpBodyDecompression(std::unique_ptr<HttpBodyParser> bodyParser); 120 virtual BodyParseResult ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody, 121 bool readEnd) override; 122 123 virtual std::optional<off_t> TotalBodySize() const noexcept; 124 125 private: 126 std::unique_ptr<HttpBodyParser> fBodyParser; 127 std::unique_ptr<BMallocIO> fDecompressorStorage; 128 std::unique_ptr<BDataIO> fDecompressingStream; 129 }; 130 131 132 } // namespace Network 133 134 } // namespace BPrivate 135 136 #endif // _B_HTTP_PARSER_H_ 137