SNode.C
Loading...
Searching...
No Matches
web::http::Parser Class Referenceabstract

#include <Parser.h>

Inheritance diagram for web::http::Parser:
Collaboration diagram for web::http::Parser:

Public Member Functions

 Parser (core::socket::stream::SocketContext *socketContext, const enum HTTPCompliance &compliance=HTTPCompliance::RFC2616|HTTPCompliance::RFC7230)
virtual ~Parser ()
std::size_t parse ()
void reset ()

Protected Types

enum struct  HTTPCompliance : unsigned short {
  RFC1945 = 0x01 << 0 , RFC2616 = 0x01 << 1 , RFC7230 = 0x01 << 2 , RFC7231 = 0x01 << 3 ,
  RFC7232 = 0x01 << 4 , RFC7233 = 0x01 << 5 , RFC7234 = 0x01 << 6 , RFC7235 = 0x01 << 7 ,
  RFC7540 = 0x01 << 8 , RFC7541 = 0x01 << 9
}
enum struct  ParserState {
  BEGIN , FIRSTLINE , HEADER , BODY ,
  TRAILER , ERROR
}

Protected Member Functions

virtual void analyzeHeader ()

Protected Attributes

enum web::http::Parser::HTTPCompliance hTTPCompliance
ParserState parserState = ParserState::BEGIN
TransferEncoding transferEncoding = TransferEncoding::HTTP10
CiStringMap< std::string > headers
std::vector< char > content
int httpMajor = 0
int httpMinor = 0
std::list< web::http::ContentDecoder * > decoderQueue
core::socket::stream::SocketContextsocketContext = nullptr
std::string line
std::size_t contentLength = 0
std::size_t contentLengthRead = 0

Static Protected Attributes

static const std::regex httpVersionRegex

Private Member Functions

virtual void begin ()=0
virtual void parseStartLine (const std::string &line)=0
virtual void parseError (int code, const std::string &reason)=0
virtual void parsingFinished ()=0
std::size_t readStartLine ()
std::size_t readHeader ()
std::size_t readContent ()
std::size_t readTrailer ()

Private Attributes

web::http::decoder::Fields headerDecoder
std::set< std::string > trailerFieldsExpected
web::http::decoder::Fields trailerDecoder

Friends

enum HTTPCompliance operator| (const enum HTTPCompliance &c1, const enum HTTPCompliance &c2)
enum HTTPCompliance operator& (const enum HTTPCompliance &c1, const enum HTTPCompliance &c2)

Detailed Description

Definition at line 71 of file Parser.h.

Member Enumeration Documentation

◆ HTTPCompliance

enum struct web::http::Parser::HTTPCompliance : unsigned short
strongprotected
Enumerator
RFC1945 
RFC2616 
RFC7230 
RFC7231 
RFC7232 
RFC7233 
RFC7234 
RFC7235 
RFC7540 
RFC7541 

Definition at line 73 of file Parser.h.

73 : unsigned short {
74 RFC1945 = 0x01 << 0, // HTTP 1.0
75 RFC2616 = 0x01 << 1, // HTTP 1.1
76 RFC7230 = 0x01 << 2, // Message Syntax and Routing
77 RFC7231 = 0x01 << 3, // Semantics and Content
78 RFC7232 = 0x01 << 4, // Conditional Requests
79 RFC7233 = 0x01 << 5, // Range Requests
80 RFC7234 = 0x01 << 6, // Caching
81 RFC7235 = 0x01 << 7, // Authentication
82 RFC7540 = 0x01 << 8, // HTTP 2.0
83 RFC7541 = 0x01 << 9 // Header Compression
84 } hTTPCompliance;

◆ ParserState

enum struct web::http::Parser::ParserState
strongprotected
Enumerator
BEGIN 
FIRSTLINE 
HEADER 
BODY 
TRAILER 
ERROR 

Definition at line 98 of file Parser.h.

98{ BEGIN, FIRSTLINE, HEADER, BODY, TRAILER, ERROR };

Constructor & Destructor Documentation

◆ Parser()

web::http::Parser::Parser ( core::socket::stream::SocketContext * socketContext,
const enum HTTPCompliance & compliance = HTTPCompliance::RFC2616 | HTTPCompliance::RFC7230 )
explicit

Definition at line 96 of file Parser.cpp.

97 : hTTPCompliance(compliance)
101 }
enum web::http::Parser::HTTPCompliance hTTPCompliance
web::http::decoder::Fields headerDecoder
Definition Parser.h:130
core::socket::stream::SocketContext * socketContext
Definition Parser.h:127
web::http::decoder::Fields trailerDecoder
Definition Parser.h:133

References web::http::decoder::Fields::Fields(), headerDecoder, socketContext, and trailerDecoder.

Referenced by web::http::server::RequestParser::RequestParser(), and web::http::client::ResponseParser::ResponseParser().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~Parser()

web::http::Parser::~Parser ( )
virtual

Definition at line 103 of file Parser.cpp.

103 {
104 reset();
105 }

References reset().

Here is the call graph for this function:

Member Function Documentation

◆ analyzeHeader()

void web::http::Parser::analyzeHeader ( )
protectedvirtual

Reimplemented in web::http::client::ResponseParser, and web::http::server::RequestParser.

Definition at line 193 of file Parser.cpp.

193 {
194 bool success = true;
195
196 // Determine message framing.
197 // RFC 9112 ยง6.3: Transfer-Encoding (chunked) overrides Content-Length.
198 const bool hasChunked = transferEncodingHasChunked(headers);
199
200 if (hasChunked) {
202 decoderQueue.emplace_back(new web::http::decoder::Chunked(socketContext));
203
204 if (headers.contains("Trailer")) {
205 std::string trailers = headers["Trailer"];
206
207 while (!trailers.empty()) {
208 std::string trailerField;
209 std::tie(trailerField, trailers) = httputils::str_split(trailers, ',');
210 httputils::str_trimm(trailerField);
211 trailerFieldsExpected.insert(trailerField);
212 trailerField.clear();
213 }
214 trailerDecoder.setFieldsExpected(trailerFieldsExpected);
215 }
216 } else if (headers.contains("Content-Length")) {
217 std::size_t length = 0;
218
219 if (!parseContentLengthStrict(headers["Content-Length"], length)) {
220 parseError(400, "Invalid Content-Length");
221 success = false;
222 } else {
223 contentLength = length;
224 decoderQueue.emplace_back(new web::http::decoder::Identity(socketContext, contentLength));
225 }
226 }
227
228 if (success) {
229 // Transfer-Encoding (other than chunked) is currently not implemented, but we keep the
230 // existing behavior of not altering the decoder queue here.
231 if (headers.contains("Transfer-Encoding")) {
232 const std::string& encoding = headers["Transfer-Encoding"];
233 if (web::http::ciContains(encoding, "compressed")) {
234 // decoderQueue.emplace_back(new web::http::decoder::Compress(socketContext));
235 }
236 if (web::http::ciContains(encoding, "deflate")) {
237 // decoderQueue.emplace_back(new web::http::decoder::Deflate(socketContext));
238 }
239 if (web::http::ciContains(encoding, "gzip")) {
240 // decoderQueue.emplace_back(new web::http::decoder::GZip(socketContext));
241 }
242 }
243
244 if (decoderQueue.empty()) {
245 decoderQueue.emplace_back(new web::http::decoder::HTTP10Response(socketContext));
246 }
247
248 if (headers.contains("Content-Encoding")) {
249 const std::string& encoding = headers["Content-Encoding"];
250
251 if (web::http::ciContains(encoding, "compressed")) {
252 // decoderQueue.emplace_back(new web::http::decoder::Compress(socketContext));
253 }
254 if (web::http::ciContains(encoding, "deflate")) {
255 // decoderQueue.emplace_back(new web::http::decoder::Deflate(socketContext));
256 }
257 if (web::http::ciContains(encoding, "gzip")) {
258 // decoderQueue.emplace_back(new web::http::decoder::GZip(socketContext));
259 }
260 if (web::http::ciContains(encoding, "br")) {
261 // decoderQueue.emplace_back(new web::http::decoder::Br(socketContext));
262 }
263 }
264 }
265 }
virtual void parseError(int code, const std::string &reason)=0
std::size_t contentLength
Definition Parser.h:143
CiStringMap< std::string > headers
Definition Parser.h:119
std::list< web::http::ContentDecoder * > decoderQueue
Definition Parser.h:125
TransferEncoding transferEncoding
Definition Parser.h:102
std::set< std::string > trailerFieldsExpected
Definition Parser.h:132
std::pair< std::string, std::string > str_split(const std::string &base, char c_middle)
std::string & str_trimm(std::string &text)
bool ciContains(const std::string &str1, const std::string &str2)
static bool transferEncodingHasChunked(CiStringMap< std::string > &headers)
Definition Parser.cpp:82
static bool parseContentLengthStrict(const std::string &s, std::size_t &out)
Definition Parser.cpp:62

References web::http::decoder::Chunked::Chunked(), web::http::Chunked, web::http::ciContains(), contentLength, decoderQueue, headers, web::http::decoder::HTTP10Response::HTTP10Response(), web::http::decoder::Identity::Identity(), web::http::parseContentLengthStrict(), parseError(), web::http::decoder::Fields::setFieldsExpected(), socketContext, httputils::str_split(), httputils::str_trimm(), trailerDecoder, trailerFieldsExpected, transferEncoding, and web::http::transferEncodingHasChunked().

Referenced by web::http::client::ResponseParser::analyzeHeader(), web::http::server::RequestParser::analyzeHeader(), and readHeader().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ begin()

virtual void web::http::Parser::begin ( )
privatepure virtual

Implemented in web::http::client::ResponseParser, and web::http::server::RequestParser.

Referenced by parse().

Here is the caller graph for this function:

◆ parse()

std::size_t web::http::Parser::parse ( )

Definition at line 125 of file Parser.cpp.

125 {
126 std::size_t ret = 0;
127 std::size_t consumed = 0;
128
129 do {
130 switch (parserState) {
132 begin();
134 [[fallthrough]];
136 ret = readStartLine();
137 break;
139 ret = readHeader();
140 break;
142 ret = readContent();
143 break;
145 ret = readTrailer();
146 break;
148 break;
149 }
150 consumed += ret;
151 } while (ret > 0 && parserState != ParserState::BEGIN && parserState != ParserState::ERROR);
152
153 return consumed;
154 }
ParserState parserState
Definition Parser.h:100
std::size_t readContent()
Definition Parser.cpp:267
virtual void begin()=0
std::size_t readTrailer()
Definition Parser.cpp:290
std::size_t readStartLine()
Definition Parser.cpp:156
std::size_t readHeader()
Definition Parser.cpp:180

References BEGIN, begin(), BODY, ERROR, FIRSTLINE, HEADER, parserState, readContent(), readHeader(), readStartLine(), readTrailer(), and TRAILER.

Referenced by apps::http::SimpleSocketProtocol::onReceivedFromPeer(), web::http::client::SocketContext::onReceivedFromPeer(), and web::http::server::SocketContext::onReceivedFromPeer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseError()

virtual void web::http::Parser::parseError ( int code,
const std::string & reason )
privatepure virtual

Implemented in web::http::client::ResponseParser, and web::http::server::RequestParser.

Referenced by analyzeHeader(), readContent(), readHeader(), and readTrailer().

Here is the caller graph for this function:

◆ parseStartLine()

virtual void web::http::Parser::parseStartLine ( const std::string & line)
privatepure virtual

Implemented in web::http::client::ResponseParser, and web::http::server::RequestParser.

Referenced by readStartLine().

Here is the caller graph for this function:

◆ parsingFinished()

virtual void web::http::Parser::parsingFinished ( )
privatepure virtual

Implemented in web::http::client::ResponseParser, and web::http::server::RequestParser.

Referenced by readContent(), and readTrailer().

Here is the caller graph for this function:

◆ readContent()

std::size_t web::http::Parser::readContent ( )
private

Definition at line 267 of file Parser.cpp.

267 {
268 ContentDecoder* contentDecoder = decoderQueue.front();
269
270 const std::size_t consumed = contentDecoder->read();
271
272 if (contentDecoder->isComplete()) {
273 contentDecoder = decoderQueue.back();
274
275 std::vector<char> chunk = contentDecoder->getContent();
276 content.insert(content.end(), chunk.begin(), chunk.end());
277
278 if (transferEncoding == TransferEncoding::Chunked && headers.contains("Trailer")) {
280 } else {
282 }
283 } else if (contentDecoder->isError()) {
284 parseError(501, "Wrong content encoding");
285 }
286
287 return consumed;
288 }
virtual void parsingFinished()=0
std::vector< char > content
Definition Parser.h:120

References web::http::Chunked, content, decoderQueue, web::http::ContentDecoder::getContent(), headers, web::http::ContentDecoder::isComplete(), web::http::ContentDecoder::isError(), parseError(), parserState, parsingFinished(), web::http::ContentDecoder::read(), TRAILER, and transferEncoding.

Referenced by parse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ readHeader()

std::size_t web::http::Parser::readHeader ( )
private

Definition at line 180 of file Parser.cpp.

180 {
181 const std::size_t consumed = headerDecoder.read();
182
183 if (headerDecoder.isError()) {
184 parseError(headerDecoder.getErrorCode(), headerDecoder.getErrorReason());
185 } else if (headerDecoder.isComplete()) {
186 headers = std::move(headerDecoder.getHeader());
188 }
189
190 return consumed;
191 }
virtual void analyzeHeader()
Definition Parser.cpp:193

References analyzeHeader(), web::http::decoder::Fields::getErrorCode(), web::http::decoder::Fields::getErrorReason(), web::http::decoder::Fields::getHeader(), headerDecoder, headers, web::http::decoder::Fields::isComplete(), web::http::decoder::Fields::isError(), parseError(), and web::http::decoder::Fields::read().

Referenced by parse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ readStartLine()

std::size_t web::http::Parser::readStartLine ( )
private

Definition at line 156 of file Parser.cpp.

156 {
157 std::size_t consumed = 0;
158 std::size_t ret = 0;
159
160 do {
161 char ch = 0;
162 ret = socketContext->readFromPeer(&ch, 1);
163
164 if (ret > 0) {
165 consumed += ret;
166 if (ch == '\r' || ch == '\n') {
167 if (ch == '\n') {
169 line.clear();
170 }
171 } else {
172 line += ch;
173 }
174 }
175 } while (ret > 0 && parserState == ParserState::FIRSTLINE);
176
177 return consumed;
178 }
virtual void parseStartLine(const std::string &line)=0
std::string line
Definition Parser.h:142

References FIRSTLINE, line, parserState, parseStartLine(), core::socket::stream::SocketContext::readFromPeer(), and socketContext.

Referenced by parse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ readTrailer()

std::size_t web::http::Parser::readTrailer ( )
private

Definition at line 290 of file Parser.cpp.

290 {
291 const std::size_t consumed = trailerDecoder.read();
292
293 if (trailerDecoder.isError()) {
294 parseError(trailerDecoder.getErrorCode(), trailerDecoder.getErrorReason());
295 } else if (trailerDecoder.isComplete()) {
296 web::http::CiStringMap<std::string>&& trailer = trailerDecoder.getHeader();
297 headers.insert(trailer.begin(), trailer.end());
299 }
300
301 return consumed;
302 }

References web::http::decoder::Fields::getErrorCode(), web::http::decoder::Fields::getErrorReason(), web::http::decoder::Fields::getHeader(), headers, web::http::decoder::Fields::isComplete(), web::http::decoder::Fields::isError(), parseError(), parsingFinished(), web::http::decoder::Fields::read(), and trailerDecoder.

Referenced by parse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset()

void web::http::Parser::reset ( )

Definition at line 107 of file Parser.cpp.

107 {
109 headers.clear();
110 content.clear();
111 httpMinor = 0;
112 httpMajor = 0;
113 line.clear();
114 contentLength = 0;
116
117 for (const ContentDecoder* contentDecoder : decoderQueue) {
118 delete contentDecoder;
119 }
120 decoderQueue.clear();
121
122 trailerFieldsExpected.clear();
123 }
std::size_t contentLengthRead
Definition Parser.h:144

References BEGIN, content, contentLength, contentLengthRead, decoderQueue, headers, httpMajor, httpMinor, line, parserState, and trailerFieldsExpected.

Referenced by web::http::client::ResponseParser::parseError(), web::http::server::RequestParser::parseError(), web::http::client::ResponseParser::parsingFinished(), web::http::server::RequestParser::parsingFinished(), and ~Parser().

Here is the caller graph for this function:

◆ operator&

enum HTTPCompliance operator& ( const enum HTTPCompliance & c1,
const enum HTTPCompliance & c2 )
friend

Definition at line 308 of file Parser.cpp.

308 {
309 return static_cast<enum Parser::HTTPCompliance>(static_cast<unsigned short>(c1) & static_cast<unsigned short>(c2));
310 }

◆ operator|

enum HTTPCompliance operator| ( const enum HTTPCompliance & c1,
const enum HTTPCompliance & c2 )
friend

Definition at line 304 of file Parser.cpp.

304 {
305 return static_cast<enum Parser::HTTPCompliance>(static_cast<unsigned short>(c1) | static_cast<unsigned short>(c2));
306 }

Member Data Documentation

◆ content

std::vector<char> web::http::Parser::content
protected

◆ contentLength

std::size_t web::http::Parser::contentLength = 0
protected

◆ contentLengthRead

std::size_t web::http::Parser::contentLengthRead = 0
protected

Definition at line 144 of file Parser.h.

Referenced by reset().

◆ decoderQueue

std::list<web::http::ContentDecoder*> web::http::Parser::decoderQueue
protected

Definition at line 125 of file Parser.h.

Referenced by analyzeHeader(), readContent(), and reset().

◆ headerDecoder

web::http::decoder::Fields web::http::Parser::headerDecoder
private

Definition at line 130 of file Parser.h.

Referenced by Parser(), and readHeader().

◆ headers

◆ hTTPCompliance

enum web::http::Parser::HTTPCompliance web::http::Parser::hTTPCompliance
protected

◆ httpMajor

◆ httpMinor

◆ httpVersionRegex

const std::regex web::http::Parser::httpVersionRegex
staticprotected

◆ line

std::string web::http::Parser::line
protected

Definition at line 142 of file Parser.h.

Referenced by readStartLine(), and reset().

◆ parserState

◆ socketContext

core::socket::stream::SocketContext* web::http::Parser::socketContext = nullptr
protected

Definition at line 127 of file Parser.h.

Referenced by analyzeHeader(), Parser(), and readStartLine().

◆ trailerDecoder

web::http::decoder::Fields web::http::Parser::trailerDecoder
private

Definition at line 133 of file Parser.h.

Referenced by analyzeHeader(), Parser(), and readTrailer().

◆ trailerFieldsExpected

std::set<std::string> web::http::Parser::trailerFieldsExpected
private

Definition at line 132 of file Parser.h.

Referenced by analyzeHeader(), and reset().

◆ transferEncoding


The documentation for this class was generated from the following files: