@@ -102,6 +102,9 @@ public HTTPParser(ParserType type) {
102102 * URL and non-URL states by looking for these.
103103 */
104104 public State parse_url_char (byte ch ) {
105+
106+ int chi = ch & 0xff ; // utility, ch without signedness for table lookups.
107+
105108 if (SPACE == ch ){
106109 throw new HTTPException ("space as url char" );
107110 }
@@ -190,7 +193,7 @@ public State parse_url_char(byte ch) {
190193 break ;
191194
192195 case req_path :
193- if (isNormalUrlChar (ch )) {
196+ if (isNormalUrlChar (chi )) {
194197 return req_path ;
195198 }
196199 switch (ch ) {
@@ -204,7 +207,7 @@ public State parse_url_char(byte ch) {
204207
205208 case req_query_string_start :
206209 case req_query_string :
207- if (isNormalUrlChar (ch )) {
210+ if (isNormalUrlChar (chi )) {
208211 return req_query_string ;
209212 }
210213
@@ -220,7 +223,7 @@ public State parse_url_char(byte ch) {
220223 break ;
221224
222225 case req_fragment_start :
223- if (isNormalUrlChar (ch )) {
226+ if (isNormalUrlChar (chi )) {
224227 return req_fragment ;
225228 }
226229 switch (ch ) {
@@ -319,24 +322,35 @@ public int execute(ParserSettings settings, ByteBuffer data) {
319322 url_mark = p ;
320323 break ;
321324 }
322- // this is where the work gets done, traverse the available data...
323- while (data .position () != data .limit ()) {
324-
325- p = data .position ();
326- int pe = data .limit ();
325+ boolean reexecute = false ;
326+ int pe = 0 ;
327+ byte ch = 0 ;
328+ int chi = 0 ;
329+ byte c = -1 ;
330+ int to_read = 0 ;
327331
328- byte ch = data .get (); // the current character to process.
329- int chi = ch & 0xff ; // utility, ch without signedness for table lookups.
330- byte c = -1 ; // utility variably used for up- and downcasing etc.
331- int to_read = 0 ; // used to keep track of how much of body, etc. is left to read
332-
333- if (parsing_header (state )) {
334- ++nread ;
335- if (nread > HTTP_MAX_HEADER_SIZE ) {
336- return error (settings , "possible buffer overflow" , data );
332+ // this is where the work gets done, traverse the available data...
333+ while (data .position () != data .limit () || reexecute ) {
334+ // p(state + ": r: " + reexecute + " :: " +p );
335+
336+ if (!reexecute ){
337+ p = data .position ();
338+ pe = data .limit ();
339+ ch = data .get (); // the current character to process.
340+ chi = ch & 0xff ; // utility, ch without signedness for table lookups.
341+ c = -1 ; // utility variably used for up- and downcasing etc.
342+ to_read = 0 ; // used to keep track of how much of body, etc. is left to read
343+
344+ if (parsing_header (state )) {
345+ ++nread ;
346+ if (nread > HTTP_MAX_HEADER_SIZE ) {
347+ return error (settings , "possible buffer overflow" , data );
348+ }
337349 }
338350 }
339- // p(state + ":" + (char)ch +":"+p);
351+ reexecute = false ;
352+ // p(state + " ::: " + ch + " : " + (((CR == ch) || (LF == ch)) ? ch : ("'" + (char)ch + "'")) +": "+p );
353+
340354 switch (state ) {
341355 /*
342356 * this state is used after a 'Connection: close' message
@@ -676,16 +690,18 @@ public int execute(ParserSettings settings, ByteBuffer data) {
676690 switch (ch ) {
677691 case SPACE :
678692 settings .call_on_url (this , data , url_mark , p -url_mark );
693+ settings .call_on_path (this , data , url_mark , p - url_mark );
679694 url_mark = -1 ;
680695 state = State .req_http_start ;
681696 break ;
682697 case CR :
683698 case LF :
684- url_mark = -1 ;
685699 http_major = 0 ;
686700 http_minor = 9 ;
687701 state = (CR == ch ) ? req_line_almost_done : header_field_start ;
688702 settings .call_on_url (this , data , url_mark , p -url_mark ); //TODO check params!!!
703+ settings .call_on_path (this , data , url_mark , p -url_mark );
704+ url_mark = -1 ;
689705 break ;
690706 default :
691707 state = parse_url_char (ch );
@@ -829,12 +845,7 @@ public int execute(ParserSettings settings, ByteBuffer data) {
829845 /* they might be just sending \n instead of \r\n so this would be
830846 * the second \n to denote the end of headers*/
831847 state = State .headers_almost_done ;
832- if (!headers_almost_done (ch , settings )) {
833- return error (settings , "header not properly completed" , data );
834- }
835- if (upgrade ) {
836- return data .position () - this .p_start ;
837- }
848+ reexecute = true ;
838849 break ;
839850 }
840851
@@ -1092,10 +1103,8 @@ public int execute(ParserSettings settings, ByteBuffer data) {
10921103 if (LF == ch ) {
10931104 settings .call_on_header_value (this , data , header_value_mark , p -header_value_mark );
10941105 header_value_mark = -1 ;
1095-
1096- if (!header_almost_done (ch )) {
1097- return error (settings , "incorrect header ending, expection LF" , data );
1098- }
1106+ state = header_almost_done ;
1107+ reexecute = true ;
10991108 break ;
11001109 }
11011110
@@ -1185,13 +1194,69 @@ public int execute(ParserSettings settings, ByteBuffer data) {
11851194 state = header_value_start ;
11861195 } else {
11871196 state = header_field_start ;
1197+ reexecute = true ;
11881198 }
11891199 break ;
11901200
11911201 case headers_almost_done :
1192- if (! headers_almost_done ( ch , settings ) ) {
1202+ if (LF != ch ) {
11931203 return error (settings , "header not properly completed" , data );
11941204 }
1205+ if (0 != (flags & F_TRAILING )) {
1206+ /* End of a chunked request */
1207+ state = new_message ();
1208+
1209+ settings .call_on_message_complete (this );
1210+ break ;
1211+ }
1212+
1213+ state = headers_done ;
1214+
1215+ if (0 != (flags & F_UPGRADE ) || HTTPMethod .HTTP_CONNECT == method ) {
1216+ upgrade = true ;
1217+ }
1218+
1219+ /* Here we call the headers_complete callback. This is somewhat
1220+ * different than other callbacks because if the user returns 1, we
1221+ * will interpret that as saying that this message has no body. This
1222+ * is needed for the annoying case of recieving a response to a HEAD
1223+ * request.
1224+ */
1225+
1226+ /* (responses to HEAD request contain a CONTENT-LENGTH header
1227+ * but no content)
1228+ *
1229+ * Consider what to do here: I don't like the idea of the callback
1230+ * interface having a different contract in the case of HEAD
1231+ * responses. The alternatives would be either to:
1232+ *
1233+ * a.) require the header_complete callback to implement a different
1234+ * interface or
1235+ *
1236+ * b.) provide an overridden execute(bla, bla, boolean
1237+ * parsingHeader) implementation ...
1238+ */
1239+
1240+ /*TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO */
1241+ if (null != settings .on_headers_complete ) {
1242+ settings .call_on_headers_complete (this );
1243+ //return;
1244+ }
1245+
1246+ // if (null != settings.on_headers_complete) {
1247+ // switch (settings.on_headers_complete.cb(parser)) {
1248+ // case 0:
1249+ // break;
1250+ //
1251+ // case 1:
1252+ // flags |= F_SKIPBODY;
1253+ // break;
1254+ //
1255+ // default:
1256+ // return p - data; /* Error */ // TODO // RuntimeException ?
1257+ // }
1258+ // }
1259+ reexecute = true ;
11951260 break ;
11961261
11971262 case headers_done :
@@ -1233,6 +1298,8 @@ public int execute(ParserSettings settings, ByteBuffer data) {
12331298 }
12341299 }
12351300 }
1301+
1302+ break ;
12361303 /******************* Header *******************/
12371304
12381305
@@ -1253,6 +1320,7 @@ public int execute(ParserSettings settings, ByteBuffer data) {
12531320 }
12541321 }
12551322
1323+ reexecute = true ;
12561324 break ;
12571325
12581326
@@ -1420,6 +1488,7 @@ public int execute(ParserSettings settings, ByteBuffer data) {
14201488 settings .call_on_header_field (this , data , header_field_mark , p -header_field_mark );
14211489 settings .call_on_header_value (this , data , header_value_mark , p -header_value_mark );
14221490 settings .call_on_url (this , data , url_mark , p -url_mark );
1491+ settings .call_on_path (this , data , url_mark , p -url_mark );
14231492
14241493 return data .position ()-this .p_start ;
14251494 } // execute
@@ -1563,69 +1632,8 @@ boolean header_almost_done(byte ch) {
15631632 return true ;
15641633 }
15651634
1566- boolean headers_almost_done (byte ch , ParserSettings settings ) {
1567- if (LF != ch ) {
1568- return false ;
1569- }
1570- if (0 != (flags & F_TRAILING )) {
1571- /* End of a chunked request */
1572- state = new_message ();
1573-
1574- settings .call_on_headers_complete (this );
1575- settings .call_on_message_complete (this );
1576-
1577- return true ;
1578- }
1579-
1580- state = headers_done ;
1581-
1582- if (0 != (flags & F_UPGRADE ) || HTTPMethod .HTTP_CONNECT == method ) {
1583- upgrade = true ;
1584- }
1585-
1586-
1587- /* Here we call the headers_complete callback. This is somewhat
1588- * different than other callbacks because if the user returns 1, we
1589- * will interpret that as saying that this message has no body. This
1590- * is needed for the annoying case of recieving a response to a HEAD
1591- * request.
1592- */
1593-
1594- /* (responses to HEAD request contain a CONTENT-LENGTH header
1595- * but no content)
1596- *
1597- * Consider what to do here: I don't like the idea of the callback
1598- * interface having a different contract in the case of HEAD
1599- * responses. The alternatives would be either to:
1600- *
1601- * a.) require the header_complete callback to implement a different
1602- * interface or
1603- *
1604- * b.) provide an overridden execute(bla, bla, boolean
1605- * parsingHeader) implementation ...
1606- */
1607-
1608- /*TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO */
1609- if (null != settings .on_headers_complete ) {
1610- settings .call_on_headers_complete (this );
1611- //return;
1612- }
1613-
1614- // if (null != settings.on_headers_complete) {
1615- // switch (settings.on_headers_complete.cb(parser)) {
1616- // case 0:
1617- // break;
1618- //
1619- // case 1:
1620- // flags |= F_SKIPBODY;
1621- // break;
1622- //
1623- // default:
1624- // return p - data; /* Error */ // TODO // RuntimeException ?
1625- // }
1626- // }
1627- return true ;
1628- } // headers_almost_done
1635+ // boolean headers_almost_done (byte ch, ParserSettings settings) {
1636+ // } // headers_almost_done
16291637
16301638
16311639 final int min (int a , int b ) {
0 commit comments