xref: /haiku/src/kits/network/libnetservices2/HttpParser.h (revision 71e29bbeea760848317843508c711f2a0b446fbb)
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