xref: /haiku/src/kits/network/libnetservices2/HttpParser.h (revision 71e29bbeea760848317843508c711f2a0b446fbb)
1e6828456SNiels Sascha Reedijk /*
2e6828456SNiels Sascha Reedijk  * Copyright 2022 Haiku Inc. All rights reserved.
3e6828456SNiels Sascha Reedijk  * Distributed under the terms of the MIT License.
4e6828456SNiels Sascha Reedijk  */
5e6828456SNiels Sascha Reedijk 
6e6828456SNiels Sascha Reedijk #ifndef _B_HTTP_PARSER_H_
7e6828456SNiels Sascha Reedijk #define _B_HTTP_PARSER_H_
8e6828456SNiels Sascha Reedijk 
9e6828456SNiels Sascha Reedijk 
10e6828456SNiels Sascha Reedijk #include <functional>
11e6828456SNiels Sascha Reedijk #include <optional>
12e6828456SNiels Sascha Reedijk 
13e6828456SNiels Sascha Reedijk #include <HttpResult.h>
14e6828456SNiels Sascha Reedijk 
15e6828456SNiels Sascha Reedijk #include "HttpBuffer.h"
16e6828456SNiels Sascha Reedijk 
17e6828456SNiels Sascha Reedijk class BMallocIO;
18e6828456SNiels Sascha Reedijk 
19e6828456SNiels Sascha Reedijk namespace BPrivate {
20e6828456SNiels Sascha Reedijk 
21e6828456SNiels Sascha Reedijk namespace Network {
22e6828456SNiels Sascha Reedijk 
23e6828456SNiels Sascha Reedijk using HttpTransferFunction = std::function<size_t(const std::byte*, size_t)>;
24e6828456SNiels Sascha Reedijk 
25e6828456SNiels Sascha Reedijk 
26*71e29bbeSNiels Sascha Reedijk enum class HttpInputStreamState { StatusLine, Fields, Body, Done };
27e6828456SNiels Sascha Reedijk 
28e6828456SNiels Sascha Reedijk 
29*71e29bbeSNiels Sascha Reedijk enum class HttpBodyType { NoContent, Chunked, FixedSize, VariableSize };
307b1d966cSNiels Sascha Reedijk 
317b1d966cSNiels Sascha Reedijk 
323c9045fbSNiels Sascha Reedijk struct BodyParseResult {
333c9045fbSNiels Sascha Reedijk 			size_t		bytesParsed;
343c9045fbSNiels Sascha Reedijk 			size_t		bytesWritten;
353c9045fbSNiels Sascha Reedijk 			bool		complete;
363c9045fbSNiels Sascha Reedijk };
373c9045fbSNiels Sascha Reedijk 
383c9045fbSNiels Sascha Reedijk 
393c9045fbSNiels Sascha Reedijk class HttpBodyParser;
403c9045fbSNiels Sascha Reedijk 
413c9045fbSNiels Sascha Reedijk 
42*71e29bbeSNiels Sascha Reedijk class HttpParser
43*71e29bbeSNiels Sascha Reedijk {
44e6828456SNiels Sascha Reedijk public:
HttpParser()45e6828456SNiels Sascha Reedijk 								HttpParser(){};
46e6828456SNiels Sascha Reedijk 
477b1d966cSNiels Sascha Reedijk 	// Explicitly mark request as having no content
483c9045fbSNiels Sascha Reedijk 			void				SetNoContent() noexcept;
497b1d966cSNiels Sascha Reedijk 
503c9045fbSNiels Sascha Reedijk 	// Parse data from response
51e6828456SNiels Sascha Reedijk 			bool				ParseStatus(HttpBuffer& buffer, BHttpStatus& status);
52e6828456SNiels Sascha Reedijk 			bool				ParseFields(HttpBuffer& buffer, BHttpFields& fields);
533c9045fbSNiels Sascha Reedijk 			size_t				ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody,
543c9045fbSNiels Sascha Reedijk 									bool readEnd);
State()553c9045fbSNiels Sascha Reedijk 			HttpInputStreamState State() const noexcept { return fStreamState; }
567b1d966cSNiels Sascha Reedijk 
577b1d966cSNiels Sascha Reedijk 	// Details on the body status
583c9045fbSNiels Sascha Reedijk 			bool				HasContent() const noexcept;
593c9045fbSNiels Sascha Reedijk 			std::optional<off_t> BodyBytesTotal() const noexcept;
603c9045fbSNiels Sascha Reedijk 			off_t				BodyBytesTransferred() const noexcept;
61e6828456SNiels Sascha Reedijk 			bool				Complete() const noexcept;
62e6828456SNiels Sascha Reedijk 
63e6828456SNiels Sascha Reedijk private:
64e6828456SNiels Sascha Reedijk 			off_t				fHeaderBytes = 0;
657b1d966cSNiels Sascha Reedijk 			BHttpStatus			fStatus;
663c9045fbSNiels Sascha Reedijk 			HttpInputStreamState fStreamState = HttpInputStreamState::StatusLine;
677b1d966cSNiels Sascha Reedijk 
683c9045fbSNiels Sascha Reedijk 	// Body
697b1d966cSNiels Sascha Reedijk 			HttpBodyType		fBodyType = HttpBodyType::VariableSize;
703c9045fbSNiels Sascha Reedijk 			std::unique_ptr<HttpBodyParser> fBodyParser = nullptr;
713c9045fbSNiels Sascha Reedijk };
72e6828456SNiels Sascha Reedijk 
733c9045fbSNiels Sascha Reedijk 
74*71e29bbeSNiels Sascha Reedijk class HttpBodyParser
75*71e29bbeSNiels Sascha Reedijk {
763c9045fbSNiels Sascha Reedijk public:
773c9045fbSNiels Sascha Reedijk 	virtual						BodyParseResult ParseBody(HttpBuffer& buffer,
783c9045fbSNiels Sascha Reedijk 									HttpTransferFunction writeToBody, bool readEnd) = 0;
793c9045fbSNiels Sascha Reedijk 
803c9045fbSNiels Sascha Reedijk 	virtual	std::optional<off_t> TotalBodySize() const noexcept;
813c9045fbSNiels Sascha Reedijk 
823c9045fbSNiels Sascha Reedijk 			off_t				TransferredBodySize() const noexcept;
833c9045fbSNiels Sascha Reedijk 
843c9045fbSNiels Sascha Reedijk protected:
853c9045fbSNiels Sascha Reedijk 			off_t				fTransferredBodySize = 0;
863c9045fbSNiels Sascha Reedijk };
873c9045fbSNiels Sascha Reedijk 
883c9045fbSNiels Sascha Reedijk 
89*71e29bbeSNiels Sascha Reedijk class HttpRawBodyParser : public HttpBodyParser
90*71e29bbeSNiels Sascha Reedijk {
913c9045fbSNiels Sascha Reedijk public:
923c9045fbSNiels Sascha Reedijk 								HttpRawBodyParser();
933c9045fbSNiels Sascha Reedijk 								HttpRawBodyParser(off_t bodyBytesTotal);
94*71e29bbeSNiels Sascha Reedijk 	virtual	BodyParseResult		ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody,
95*71e29bbeSNiels Sascha Reedijk 									bool readEnd) override;
963c9045fbSNiels Sascha Reedijk 	virtual	std::optional<off_t> TotalBodySize() const noexcept override;
973c9045fbSNiels Sascha Reedijk 
983c9045fbSNiels Sascha Reedijk private:
993c9045fbSNiels Sascha Reedijk 			std::optional<off_t> fBodyBytesTotal;
1003c9045fbSNiels Sascha Reedijk };
1013c9045fbSNiels Sascha Reedijk 
1023c9045fbSNiels Sascha Reedijk 
103*71e29bbeSNiels Sascha Reedijk class HttpChunkedBodyParser : public HttpBodyParser
104*71e29bbeSNiels Sascha Reedijk {
1053c9045fbSNiels Sascha Reedijk public:
106*71e29bbeSNiels Sascha Reedijk 	virtual BodyParseResult ParseBody(
107*71e29bbeSNiels Sascha Reedijk 		HttpBuffer& buffer, HttpTransferFunction writeToBody, bool readEnd) override;
1083c9045fbSNiels Sascha Reedijk 
1093c9045fbSNiels Sascha Reedijk private:
110*71e29bbeSNiels Sascha Reedijk 	enum { ChunkSize, ChunkEnd, Chunk, Trailers, Complete } fChunkParserState = ChunkSize;
111e6828456SNiels Sascha Reedijk 	off_t fRemainingChunkSize = 0;
112e6828456SNiels Sascha Reedijk 	bool fLastChunk = false;
1133c9045fbSNiels Sascha Reedijk };
114e6828456SNiels Sascha Reedijk 
115e6828456SNiels Sascha Reedijk 
116*71e29bbeSNiels Sascha Reedijk class HttpBodyDecompression : public HttpBodyParser
117*71e29bbeSNiels Sascha Reedijk {
1183c9045fbSNiels Sascha Reedijk public:
119*71e29bbeSNiels Sascha Reedijk 								HttpBodyDecompression(std::unique_ptr<HttpBodyParser> bodyParser);
120*71e29bbeSNiels Sascha Reedijk 	virtual	BodyParseResult		ParseBody(HttpBuffer& buffer, HttpTransferFunction writeToBody,
121*71e29bbeSNiels Sascha Reedijk 									bool readEnd) override;
122e6828456SNiels Sascha Reedijk 
1233c9045fbSNiels Sascha Reedijk 	virtual	std::optional<off_t> TotalBodySize() const noexcept;
1243c9045fbSNiels Sascha Reedijk 
1253c9045fbSNiels Sascha Reedijk private:
1263c9045fbSNiels Sascha Reedijk 			std::unique_ptr<HttpBodyParser> fBodyParser;
1273c9045fbSNiels Sascha Reedijk 			std::unique_ptr<BMallocIO> fDecompressorStorage;
1283c9045fbSNiels Sascha Reedijk 			std::unique_ptr<BDataIO> fDecompressingStream;
129e6828456SNiels Sascha Reedijk };
130e6828456SNiels Sascha Reedijk 
131e6828456SNiels Sascha Reedijk 
132e6828456SNiels Sascha Reedijk } // namespace Network
133e6828456SNiels Sascha Reedijk 
134e6828456SNiels Sascha Reedijk } // namespace BPrivate
135e6828456SNiels Sascha Reedijk 
136e6828456SNiels Sascha Reedijk #endif // _B_HTTP_PARSER_H_
137