75
75
76
76
/* HTTP OK Status-Line. */
77
77
#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"
78
79
#define HTTP_STATUS_CODE_OK 200
79
80
80
81
/* Various header lines for test response templates. */
103
104
HTTP_TEST_VARY_HEADER_LINE \
104
105
HTTP_TEST_P3P_HEADER_LINE \
105
106
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 )
111
127
112
128
/* Template HTTP PUT response. This has no body. */
113
129
#define HTTP_TEST_RESPONSE_PUT \
@@ -235,6 +251,9 @@ static HTTPRequestHeaders_t requestHeaders = { 0 };
235
251
/* Header parsing callback shared among the tests. */
236
252
static HTTPClient_ResponseHeaderParsingCallback_t headerParsingCallback = { 0 };
237
253
254
+ /* Flag to indicate this callback is called. */
255
+ static int statusCompleteCallbackFlag = 0 ;
256
+
238
257
/* A mocked timer query function that increments on every call. */
239
258
static uint32_t getTestTime ( void )
240
259
{
@@ -432,6 +451,7 @@ static void helper_parse_status_line( const char ** pNext,
432
451
const llhttp_settings_t * pSettings )
433
452
{
434
453
const char * pReasonPhraseStart = NULL ;
454
+ const char * pNextLineStart = NULL ;
435
455
size_t reasonPhraseStartLen = 0 ;
436
456
437
457
/* 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,
440
460
* always string literals. strchr() should not be used in application code. */
441
461
* pNext = strchr ( * pNext , SPACE_CHARACTER ); /* Get the space before the status-code. */
442
462
* 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
+
448
471
pParser -> status_code = 200 ;
449
- pSettings -> on_status ( pParser ,
450
- pReasonPhraseStart ,
451
- reasonPhraseStartLen );
452
472
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
+ }
454
493
}
455
494
456
495
/* Mock helper that parses all of the headers starting from pNext. */
@@ -805,6 +844,7 @@ void setUp( void )
805
844
response .pBuffer = httpBuffer ;
806
845
response .bufferLen = sizeof ( httpBuffer );
807
846
response .pHeaderParsingCallback = & headerParsingCallback ;
847
+ statusCompleteCallbackFlag = 0 ;
808
848
809
849
/* Ignore third-party init functions that return void. */
810
850
llhttp_init_Ignore ();
@@ -846,6 +886,72 @@ void test_HTTPClient_Send_HEAD_request_parse_whole_response( void )
846
886
847
887
/*-----------------------------------------------------------*/
848
888
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
+
849
955
/* Test successfully parsing a response to a PUT request. The full response
850
956
* message is present in the response buffer on the first network read. */
851
957
void test_HTTPClient_Send_PUT_request_parse_whole_response ( void )
@@ -1757,6 +1863,25 @@ void test_HTTPClient_Send_parsing_errors( void )
1757
1863
0 );
1758
1864
TEST_ASSERT_EQUAL ( HTTPSecurityAlertInvalidContentLength , returnStatus );
1759
1865
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
+
1760
1885
/* Use -1 to indicate an unknown error. */
1761
1886
httpParsingErrno = -1 ;
1762
1887
returnStatus = HTTPClient_Send ( & transportInterface ,
0 commit comments