@@ -9,7 +9,7 @@ HTTPParser::HTTPParser(ClientFD_t ClientFD) :
99 _RequestCountGet(0 ),
1010 _RequestCountPost(0 ),
1111 _RequestCountPostAS(0 ),
12- _HTTPRequest (" " )
12+ _HTTPRequestBuffer (" " )
1313{
1414 DBG (120 , " Constructor" );
1515}
@@ -21,121 +21,193 @@ HTTPParser::~HTTPParser()
2121
2222void HTTPParser::appendBuffer (const char * BufferRef, const uint16_t BufferSize)
2323{
24- _HTTPRequest = _HTTPRequest + string (&BufferRef[0 ], BufferSize);
25- String::hexout (_HTTPRequest);
26- // DBG(250, "HTTPRequest:'" << _HTTPRequest << "'");
27- _splitRequests ();
24+ _HTTPRequestBuffer = _HTTPRequestBuffer + string (&BufferRef[0 ], BufferSize);
25+ // String::hexout(_HTTPRequestBuffer);
26+ DBG (250 , " _HTTPRequestBuffer:'" << _HTTPRequestBuffer << " '" );
27+
28+ // -> only process on min 1 valid request
29+ const size_t EndMarkerFound = _HTTPRequestBuffer.find (" \r\n\r\n " );
30+
31+ if (EndMarkerFound != string::npos) {
32+ _splitRequests ();
33+ }
2834}
2935
3036void HTTPParser::_splitRequests ()
3137{
32- // DBG(180, "splitRequests Buffer:'" << _HTTPRequest << "'");
38+ // DBG(180, "splitRequests Buffer:'" << _HTTPRequestBuffer << "'");
3339
3440 // - reset request counters
3541 _RequestCountGet = 0 ;
3642 _RequestCountPost = 0 ;
3743 _RequestCountPostAS = 0 ;
3844
39- // -> reset incomplete request string
40- string incompleteRequest (" " );
41-
42- // -> check for existing valid request end marker
43- size_t LastDelimiterPos = _HTTPRequest.rfind (" \r\n\r\n " );
44- DBG (120 , " LastDelimiterPos:" << LastDelimiterPos);
45-
46- // -> if min 1 full valid request && rest without end marker
47- if (LastDelimiterPos != string::npos && LastDelimiterPos != _HTTPRequest.length ()-4 ) {
48-
49- // -> put incomplete last request into tmp string
50- incompleteRequest = _HTTPRequest.substr (LastDelimiterPos+4 );
51-
52- // -> remove incomplete last request from _HTTPRequest
53- _HTTPRequest.replace (_HTTPRequest.begin ()+LastDelimiterPos+4 , _HTTPRequest.end (), " " );
54- }
45+ // -> reset _SplittedRequests vector
46+ _SplittedRequests.clear ();
5547
5648 // -> split requests into _SplittedRequests vector
57- _SplittedRequests.clear ();
58- String::split (_HTTPRequest, " \r\n\r\n " , _SplittedRequests);
49+ String::split (_HTTPRequestBuffer, " \r\n\r\n " , _SplittedRequests);
5950 _RequestCount = _SplittedRequests.size ();
6051 DBG (120 , " splitRequests count after splitted into Vector:" << _RequestCount);
61-
62- // -> "restore" incomplete last request buffer
63- _HTTPRequest = incompleteRequest;
6452}
6553
66- uint HTTPParser::processRequests (SharedMemAddress_t SHMGetRequests, const ASRequestHandlerRef_t ASRequestHandlerRef)
54+ size_t HTTPParser::processRequests (SharedMemAddress_t SHMGetRequests, const ASRequestHandlerRef_t ASRequestHandlerRef)
6755{
56+ // - set get requests SHM base
6857 setBaseAddress (SHMGetRequests);
6958
70- for (auto &Request:_SplittedRequests) {
71- _processRequestProperties (Request, ASRequestHandlerRef);
59+ // - iterate over splitted requests
60+ for (size_t i=0 ; i<_SplittedRequests.size (); ++i) {
61+ _processRequestProperties (i, ASRequestHandlerRef);
62+ }
63+
64+ // - restore truncated requests
65+ const auto LastElementIndex = _SplittedRequests.size ();
66+
67+ if (LastElementIndex > 0 ) {
68+ const auto LastElementVal = _SplittedRequests.at (LastElementIndex-1 );
69+
70+ if (!LastElementVal.empty ()) {
71+ _HTTPRequestBuffer.append (LastElementVal);
72+ }
73+ }
74+
75+ if (LastElementIndex > 1 ) {
76+ const auto LastElementPrevVal = _SplittedRequests.at (LastElementIndex-2 );
77+
78+ if (!LastElementPrevVal.empty ()) {
79+ _HTTPRequestBuffer.append (LastElementPrevVal);
80+ }
7281 }
7382
7483 return _RequestCountGet;
7584}
7685
77- void HTTPParser::_processRequestProperties (string& Request , const ASRequestHandlerRef_t ASRequestHandlerRef)
86+ void HTTPParser::_processRequestProperties (const size_t Index , const ASRequestHandlerRef_t ASRequestHandlerRef)
7887{
79- // DBG(180, "HTTP Request:'" << Request << "'");
88+ // - get request ref at vector index
89+ auto Request = _SplittedRequests.at (Index);
90+
91+ // - on empty request return
92+ if (Request.empty ()) { return ; }
8093
8194 BasePropsResult_t BasePropsFound;
8295 this ->_parseRequestProperties (Request, BasePropsFound);
8396
8497 DBG (140 , " HTTP Version:" << BasePropsFound.at (0 ) << " File:" << BasePropsFound.at (1 ) << " Method:" << BasePropsFound.at (2 ));
85- DBG (140 , " HTTP Payload (c_str) :" << Request.c_str ());
98+ DBG (140 , " Complete Request :" << Request.c_str ());
8699
87- // - check HTTP/1.2 (currently unimplemented)
88- const size_t HTTPVersion1_2Found = BasePropsFound. at ( 0 ). find ( " HTTP/1.2 " ) ;
100+ // - temp hardcode HTTPVersion
101+ uint16_t HTTPVersion = 1 ;
89102
90- // - if not HTTP/1.1, do not process further
103+ // - check HTTP/1.2 or HTTP/1.2 (currently unimplemented)
91104 const size_t HTTPVersion1_1Found = BasePropsFound.at (0 ).find (" HTTP/1.1" );
105+ const size_t HTTPVersion1_2Found = BasePropsFound.at (2 ).find (" HTTP/1.2" );
92106
93- const uint16_t HTTPMethod = (BasePropsFound.at (2 ).find (" POST" ) != string::npos) ? 2 : 1 ;
94- const uint16_t HTTPVersion = (BasePropsFound.at (0 ).find (" HTTP/1.1" ) != string::npos) ? 1 : 2 ;
107+ // - if not HTTP/1.1 set request to "" in vector element, return
108+ if (HTTPVersion1_1Found == string::npos) {
109+ _SplittedRequests.at (Index) = " " ;
110+ return ;
111+ }
95112
96- // - check if POST request is an AS request
97- const size_t PythonReqFound = BasePropsFound.at (1 ).find (" /python/" );
113+ // - check for method GET || POST
114+ const size_t HTTPMethodPOST = BasePropsFound.at (2 ).find (" POST" );
115+ const size_t HTTPMethodGET = BasePropsFound.at (2 ).find (" GET" );
98116
99- // - get unique request nr
100- uint16_t RequestNr = getNextReqNr () ;
117+ // - set numerical http method (GET: 1, POST: 2)
118+ uint16_t HTTPMethod = 0 ;
101119
102- DBG (140 , " HTTP RequestNr:" << RequestNr << " HTTPVersion:" << HTTPVersion << " HTTPMethod:" << HTTPMethod);
120+ if (HTTPMethodGET != string::npos) { HTTPMethod = 1 ; }
121+ if (HTTPMethodPOST != string::npos) { HTTPMethod = 2 ; }
122+
123+ DBG (140 , " HTTPMethod:" << HTTPMethod);
124+
125+ // - if not GET || POST, set request to "" in vector element, return
126+ if (HTTPMethod == 0 ) {
127+ _SplittedRequests.at (Index) = " " ;
128+ return ;
129+ }
103130
104- if (HTTPMethod == 2 ) {
131+ // - check if POST request is a POSTAS request
132+ const size_t PythonReqFound = BasePropsFound.at (1 ).find (" /python/" );
133+
134+ // - if not POSTAS, set request to "" in vector element, return
135+ if (HTTPMethod == 2 && PythonReqFound == string::npos) {
105136 ++this ->_RequestCountPost ;
137+ _SplittedRequests.at (Index) = " " ;
138+ return ;
106139 }
107140
108- if (HTTPMethod == 2 && PythonReqFound != BasePropsFound.at (1 ).npos ) {
141+ // - get unique request nr
142+ const uint16_t RequestNr = getNextReqNr ();
143+
144+ DBG (140 , " HTTP RequestNr:" << RequestNr);
145+
146+ if (HTTPMethod == 2 && PythonReqFound != string::npos) {
109147
110- DBG (140 , " Python Request:" << Request);
148+ DBG (140 , " Request Type PythonAS :" << Request);
111149
112- ++this ->_RequestCountPostAS ;
150+ // -> check first line end exists
151+ size_t FirstLineEndMarker = Request.find (" \r\n " );
152+
153+ // -> if not: truncated
154+ if (FirstLineEndMarker == string::npos) {
155+ DBG (200 , " Truncated POST Request - no First Line end" );
156+ return ;
157+ }
113158
114159 // -> cut first properties line from request
115- size_t FirstLineEndMarker = Request.find (" \n\r " );
116- Request.replace (0 , FirstLineEndMarker+2 , " " );
160+ if (FirstLineEndMarker != string::npos) {
161+ Request.replace (0 , FirstLineEndMarker+2 , " " );
162+ }
117163
118164 RequestHeaderResult_t Headers;
119165 this ->_parseRequestHeaders (Request, Headers);
120166
121- auto ContentBytes = stoi (Headers.at (" Content-Length" ));
122- string Payload = Request.substr (Request.length ()-ContentBytes, ContentBytes);
167+ uint ContentBytes = 0 ;
123168
124- DBG (140 , " HTTP POST-AS payload:" << Payload);
169+ // - try get content length header
170+ try {
171+ ContentBytes = stoi (Headers.at (" Content-Length" ));
172+ }
173+ catch (const std::exception& e) {
174+ DBG (200 , " Truncated POST Request - no Content-Length" );
175+ return ;
176+ }
125177
126- // - add ASRequestHandler request
127- ASRequestHandlerRef->addRequest ({
128- Headers.at (" Host" ),
129- _ClientFD,
130- HTTPMethod,
131- HTTPVersion,
132- RequestNr,
133- Payload
134- });
178+ // - try get next request +payload at vector index +1
179+ try {
180+ auto NextRequest = _SplittedRequests.at (Index+1 );
181+
182+ if (NextRequest.length () >= ContentBytes) {
183+ string Payload = NextRequest.substr (0 , ContentBytes);
184+ NextRequest.replace (0 , ContentBytes, " " );
185+ DBG (140 , " HTTP POST-AS Payload:" << Payload);
186+
187+ // - increment request count
188+ ++this ->_RequestCountPostAS ;
189+
190+ // - add ASRequestHandler request
191+ ASRequestHandlerRef->addRequest ({
192+ Headers.at (" Host" ),
193+ _ClientFD,
194+ HTTPMethod,
195+ HTTPVersion,
196+ RequestNr,
197+ Payload
198+ });
199+ }
200+ }
201+ catch (const std::exception& e) {
202+ DBG (200 , " Truncated POST Request - no Payload" );
203+ return ;
204+ }
135205 }
136206
137207 if (HTTPMethod == 1 ) {
138208
209+ DBG (140 , " Request Type GET:" << Request);
210+
139211 ++this ->_RequestCountGet ;
140212
141213 // - set values in get requests shared memory
@@ -168,7 +240,7 @@ void HTTPParser::_parseRequestProperties(string& Request, BasePropsResultRef_t R
168240 // - find first line endline
169241 size_t StartPos = Request.find (" \r\n " );
170242
171- // -> if no headers (no \n), set start pos to end of string
243+ // -> if no headers (no \r\ n), set start pos to end of string
172244 if (StartPos == string::npos) {
173245 StartPos = Request.length ();
174246 }
@@ -187,13 +259,19 @@ void HTTPParser::_parseRequestHeaders(string& Request, RequestHeaderResultRef_t
187259 vector<string> Lines;
188260 String::split (Request, " \r\n " , Lines);
189261
262+ // - add last line (unsplitted)
263+ const size_t LastDelimiter = Request.rfind (" \r\n " );
264+ if (LastDelimiter != string::npos) {
265+ Lines.push_back (Request.substr (LastDelimiter+2 , Request.length ()));
266+ }
267+
190268 // - loop over lines, split, put into result map
191269 for (auto &Line:Lines) {
192270
193271 DBG (120 , " Line:'" << Line << " '" );
194272
195273 vector<string> HeaderPair;
196- if (Line.find (' : ' ) != string::npos) {
274+ if (Line.find (" : " ) != string::npos) {
197275
198276 String::rsplit (Line, Line.length (), " : " , HeaderPair);
199277 string HeaderID = HeaderPair.at (1 );
0 commit comments