7575
7676/* HTTP OK Status-Line. */
7777#define HTTP_STATUS_LINE_OK "HTTP/1.1 200 OK\r\n"
78+ #define HTTP_STATUS_LINE_NO_REASON_PHRASE "HTTP/1.1 200\r\n"
7879#define HTTP_STATUS_CODE_OK 200
7980
8081/* Various header lines for test response templates. */
103104 HTTP_TEST_VARY_HEADER_LINE \
104105 HTTP_TEST_P3P_HEADER_LINE \
105106 HTTP_TEST_XSERVER_HEADER_LINE HTTP_HEADER_LINE_SEPARATOR
106- #define HTTP_TEST_RESPONSE_HEAD_LENGTH ( sizeof( HTTP_TEST_RESPONSE_HEAD ) - 1U )
107- #define HTTP_TEST_RESPONSE_HEAD_HEADER_COUNT 7
108- #define HTTP_TEST_RESPONSE_HEAD_CONTENT_LENGTH 43
109- #define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_FIELD_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_FIELD ) - 2U )
110- #define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_VALUE_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_VALUE ) - 2U )
107+ #define HTTP_TEST_RESPONSE_HEAD_LENGTH ( sizeof( HTTP_TEST_RESPONSE_HEAD ) - 1U )
108+ #define HTTP_TEST_RESPONSE_HEAD_HEADER_COUNT 7
109+ #define HTTP_TEST_RESPONSE_HEAD_CONTENT_LENGTH 43
110+ #define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_FIELD_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_FIELD ) - 2U )
111+ #define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_VALUE_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_VALUE ) - 2U )
112+
113+ #define HTTP_TEST_RESPONSE_HEAD_2 \
114+ HTTP_STATUS_LINE_NO_REASON_PHRASE \
115+ HTTP_TEST_CONTENT_LENGTH_HEADER_LINE \
116+ HTTP_TEST_CONNECTION_CLOSE_HEADER_LINE \
117+ HTTP_TEST_DATE_HEADER_LINE \
118+ HTTP_TEST_ETAG_HEADER_LINE \
119+ HTTP_TEST_VARY_HEADER_LINE \
120+ HTTP_TEST_P3P_HEADER_LINE \
121+ HTTP_TEST_XSERVER_HEADER_LINE HTTP_HEADER_LINE_SEPARATOR
122+ #define HTTP_TEST_RESPONSE_HEAD_2_LENGTH ( sizeof( HTTP_TEST_RESPONSE_HEAD_2 ) - 1U )
123+ #define HTTP_TEST_RESPONSE_HEAD_2_HEADER_COUNT 7
124+ #define HTTP_TEST_RESPONSE_HEAD_2_CONTENT_LENGTH 43
125+ #define HTTP_TEST_RESPONSE_HEAD_2_PARTIAL_HEADER_FIELD_LENGTH ( sizeof( HTTP_STATUS_LINE_NO_REASON_PHRASE ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_FIELD ) - 2U )
126+ #define HTTP_TEST_RESPONSE_HEAD_2_PARTIAL_HEADER_VALUE_LENGTH ( sizeof( HTTP_STATUS_LINE_NO_REASON_PHRASE ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_VALUE ) - 2U )
111127
112128/* Template HTTP PUT response. This has no body. */
113129#define HTTP_TEST_RESPONSE_PUT \
@@ -235,6 +251,9 @@ static HTTPRequestHeaders_t requestHeaders = { 0 };
235251/* Header parsing callback shared among the tests. */
236252static HTTPClient_ResponseHeaderParsingCallback_t headerParsingCallback = { 0 };
237253
254+ /* Flag to indicate this callback is called. */
255+ static int statusCompleteCallbackFlag = 0 ;
256+
238257/* A mocked timer query function that increments on every call. */
239258static uint32_t getTestTime ( void )
240259{
@@ -432,6 +451,7 @@ static void helper_parse_status_line( const char ** pNext,
432451 const llhttp_settings_t * pSettings )
433452{
434453 const char * pReasonPhraseStart = NULL ;
454+ const char * pNextLineStart = NULL ;
435455 size_t reasonPhraseStartLen = 0 ;
436456
437457 /* For purposes of unit testing the response is well formed in the non-error
@@ -440,17 +460,36 @@ static void helper_parse_status_line( const char ** pNext,
440460 * always string literals. strchr() should not be used in application code. */
441461 * pNext = strchr ( * pNext , SPACE_CHARACTER ); /* Get the space before the status-code. */
442462 * pNext += SPACE_CHARACTER_LEN ;
443- * pNext = strchr ( * pNext , SPACE_CHARACTER ); /* Get the space before the reason-phrase. */
444- * pNext += SPACE_CHARACTER_LEN ;
445- pReasonPhraseStart = * pNext ;
446- * pNext = strstr ( * pNext , HTTP_HEADER_LINE_SEPARATOR );
447- reasonPhraseStartLen = ( size_t ) ( * pNext - pReasonPhraseStart );
463+ /* pNext points to the status code now. */
464+
465+ pReasonPhraseStart = strchr ( * pNext , SPACE_CHARACTER );
466+ pReasonPhraseStart = & ( pReasonPhraseStart [ SPACE_CHARACTER_LEN ] );
467+
468+ pNextLineStart = strstr ( * pNext , HTTP_HEADER_LINE_SEPARATOR );
469+ pNextLineStart = & ( pNextLineStart [ HTTP_HEADER_LINE_SEPARATOR_LEN ] );
470+
448471 pParser -> status_code = 200 ;
449- pSettings -> on_status ( pParser ,
450- pReasonPhraseStart ,
451- reasonPhraseStartLen );
452472
453- * pNext += HTTP_HEADER_LINE_SEPARATOR_LEN ;
473+ /* Check if the reason phrase exist in the header and call the corresponding callback.
474+ * Reason phrase "OK" exists in the response "HTTP/1.1 200 OK\r\n". The callback
475+ * on_status is called.
476+ * Reason phrase doesn't exist in the response "HTTP/1.1 200\r\n". The callback
477+ * on_status_complete is called. */
478+ if ( pNextLineStart > pReasonPhraseStart )
479+ {
480+ reasonPhraseStartLen = ( size_t ) ( pNextLineStart - pReasonPhraseStart );
481+ reasonPhraseStartLen = reasonPhraseStartLen - HTTP_HEADER_LINE_SEPARATOR_LEN ;
482+ pSettings -> on_status ( pParser ,
483+ pReasonPhraseStart ,
484+ reasonPhraseStartLen );
485+ * pNext = pNextLineStart ;
486+ }
487+ else
488+ {
489+ statusCompleteCallbackFlag = 1 ;
490+ pSettings -> on_status_complete ( pParser );
491+ * pNext = pNextLineStart ;
492+ }
454493}
455494
456495/* Mock helper that parses all of the headers starting from pNext. */
@@ -805,6 +844,7 @@ void setUp( void )
805844 response .pBuffer = httpBuffer ;
806845 response .bufferLen = sizeof ( httpBuffer );
807846 response .pHeaderParsingCallback = & headerParsingCallback ;
847+ statusCompleteCallbackFlag = 0 ;
808848
809849 /* Ignore third-party init functions that return void. */
810850 llhttp_init_Ignore ();
@@ -846,6 +886,72 @@ void test_HTTPClient_Send_HEAD_request_parse_whole_response( void )
846886
847887/*-----------------------------------------------------------*/
848888
889+ /* Test successfully parsing a response to a HEAD request. The full response
890+ * message is present in the response buffer on the first network read. */
891+ void test_HTTPClient_Send_HEAD_request_no_parse_body ( void )
892+ {
893+ HTTPStatus_t returnStatus = HTTPSuccess ;
894+
895+ llhttp_execute_Stub ( llhttp_execute_whole_response );
896+
897+ response .respOptionFlags |= HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG ;
898+
899+ returnStatus = HTTPClient_Send ( & transportInterface ,
900+ & requestHeaders ,
901+ NULL ,
902+ 0 ,
903+ & response ,
904+ 0 );
905+ TEST_ASSERT_EQUAL ( HTTPSuccess , returnStatus );
906+ TEST_ASSERT_EQUAL ( NULL , response .pBody );
907+ TEST_ASSERT_EQUAL ( 0U , response .bodyLen );
908+ TEST_ASSERT_EQUAL ( response .pBuffer + ( sizeof ( HTTP_STATUS_LINE_OK ) - 1U ), response .pHeaders );
909+ TEST_ASSERT_EQUAL ( HTTP_TEST_RESPONSE_HEAD_LENGTH - ( sizeof ( HTTP_STATUS_LINE_OK ) - 1U ) - HTTP_HEADER_END_INDICATOR_LEN ,
910+ response .headersLen );
911+ TEST_ASSERT_EQUAL ( HTTP_STATUS_CODE_OK , response .statusCode );
912+ TEST_ASSERT_EQUAL ( HTTP_TEST_RESPONSE_HEAD_CONTENT_LENGTH , response .contentLength );
913+ TEST_ASSERT_EQUAL ( HTTP_TEST_RESPONSE_HEAD_HEADER_COUNT , response .headerCount );
914+ TEST_ASSERT_BITS_HIGH ( HTTP_RESPONSE_CONNECTION_CLOSE_FLAG , response .respFlags );
915+ TEST_ASSERT_BITS_LOW ( HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG , response .respFlags );
916+ }
917+
918+ /*-----------------------------------------------------------*/
919+
920+ /* Test successfully parsing a response to a HEAD request. The full response
921+ * message is present in the response buffer on the first network read. The response
922+ * contains a status code but without a reason string. The on_status_complete is called
923+ * in this case. */
924+ void test_HTTPClient_Send_HEAD_request_parse_whole_response_no_reason_string ( void )
925+ {
926+ HTTPStatus_t returnStatus = HTTPSuccess ;
927+
928+ pNetworkData = ( uint8_t * ) HTTP_TEST_RESPONSE_HEAD_2 ;
929+ networkDataLen = HTTP_TEST_RESPONSE_HEAD_2_LENGTH ;
930+
931+ llhttp_execute_Stub ( llhttp_execute_whole_response );
932+
933+ returnStatus = HTTPClient_Send ( & transportInterface ,
934+ & requestHeaders ,
935+ NULL ,
936+ 0 ,
937+ & response ,
938+ 0 );
939+ TEST_ASSERT_EQUAL ( HTTPSuccess , returnStatus );
940+ TEST_ASSERT_EQUAL ( NULL , response .pBody );
941+ TEST_ASSERT_EQUAL ( 0U , response .bodyLen );
942+ TEST_ASSERT_EQUAL ( response .pBuffer + ( sizeof ( HTTP_STATUS_LINE_NO_REASON_PHRASE ) - 1U ), response .pHeaders );
943+ TEST_ASSERT_EQUAL ( HTTP_TEST_RESPONSE_HEAD_2_LENGTH - ( sizeof ( HTTP_STATUS_LINE_NO_REASON_PHRASE ) - 1U ) - HTTP_HEADER_END_INDICATOR_LEN ,
944+ response .headersLen );
945+ TEST_ASSERT_EQUAL ( HTTP_STATUS_CODE_OK , response .statusCode );
946+ TEST_ASSERT_EQUAL ( HTTP_TEST_RESPONSE_HEAD_2_CONTENT_LENGTH , response .contentLength );
947+ TEST_ASSERT_EQUAL ( HTTP_TEST_RESPONSE_HEAD_2_HEADER_COUNT , response .headerCount );
948+ TEST_ASSERT_BITS_HIGH ( HTTP_RESPONSE_CONNECTION_CLOSE_FLAG , response .respFlags );
949+ TEST_ASSERT_BITS_LOW ( HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG , response .respFlags );
950+ TEST_ASSERT_EQUAL ( 1 , statusCompleteCallbackFlag );
951+ }
952+
953+ /*-----------------------------------------------------------*/
954+
849955/* Test successfully parsing a response to a PUT request. The full response
850956 * message is present in the response buffer on the first network read. */
851957void test_HTTPClient_Send_PUT_request_parse_whole_response ( void )
@@ -1757,6 +1863,25 @@ void test_HTTPClient_Send_parsing_errors( void )
17571863 0 );
17581864 TEST_ASSERT_EQUAL ( HTTPSecurityAlertInvalidContentLength , returnStatus );
17591865
1866+ httpParsingErrno = HPE_PAUSED ;
1867+ returnStatus = HTTPClient_Send ( & transportInterface ,
1868+ & requestHeaders ,
1869+ NULL ,
1870+ 0 ,
1871+ & response ,
1872+ 0 );
1873+ TEST_ASSERT_EQUAL ( HTTPParserPaused , returnStatus );
1874+
1875+ httpParsingErrno = HPE_PAUSED ;
1876+ response .respOptionFlags |= HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG ;
1877+ returnStatus = HTTPClient_Send ( & transportInterface ,
1878+ & requestHeaders ,
1879+ NULL ,
1880+ 0 ,
1881+ & response ,
1882+ 0 );
1883+ TEST_ASSERT_EQUAL ( HTTPNoResponse , returnStatus );
1884+
17601885 /* Use -1 to indicate an unknown error. */
17611886 httpParsingErrno = -1 ;
17621887 returnStatus = HTTPClient_Send ( & transportInterface ,
0 commit comments