Skip to content

Commit

Permalink
ability to pause parsing after headers
Browse files Browse the repository at this point in the history
  • Loading branch information
cryi committed Jan 17, 2024
1 parent ae95ec7 commit 00677cb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 5 deletions.
22 changes: 21 additions & 1 deletion source/core_http_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,13 @@ static int httpParserOnHeadersCompleteCallback( llhttp_t * pHttpParser )

LogDebug( ( "Response parsing: Found the end of the headers." ) );

/* If there is HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG opt-in we should stop
* parsing here. */
if ( pResponse->respOptionFlags & HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG ) {
shouldContinueParse = LLHTTP_PAUSE_PARSING;
pResponse->pBody = (const uint8_t*)pParsingContext->pBufferCur;
}

return shouldContinueParse;
}

Expand Down Expand Up @@ -1101,7 +1108,10 @@ static HTTPStatus_t processLlhttpError( const llhttp_t * pHttpParser )
"found when it shouldn't have been." ) );
returnStatus = HTTPSecurityAlertInvalidContentLength;
break;

case HPE_PAUSED:
LogInfo(("User intervention: Parsing stopped by user."));
returnStatus = HTTPParserPaused;
break;
/* All other error cases cannot be triggered and indicate an error in the
* third-party parsing library if found. */
default:
Expand Down Expand Up @@ -2086,6 +2096,12 @@ HTTPStatus_t HTTPClient_ReceiveAndParseHttpResponse( const TransportInterface_t
( totalReceived < pResponse->bufferLen ) ) ? 1U : 0U;
}

if ( returnStatus == HTTPParserPaused && pResponse->respOptionFlags & HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG) {
returnStatus = HTTPSuccess;
/* There may be dangling data if we parse with do not parse body flag. To let libraries built on top of corehttp we expose it through body. */
pResponse->bodyLen = totalReceived - ((uint8_t *)pResponse->pBody - pResponse->pBuffer);
}

if( returnStatus == HTTPSuccess )
{
/* If there are errors in receiving from the network or during parsing,
Expand Down Expand Up @@ -2607,6 +2623,10 @@ const char * HTTPClient_strerror( HTTPStatus_t status )
str = "HTTPSecurityAlertInvalidContentLength";
break;

case HTTPParserPaused:
str = "HTTPParserPaused";
break;

case HTTPParserInternalError:
str = "HTTPParserInternalError";
break;
Expand Down
45 changes: 41 additions & 4 deletions source/include/core_http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,26 @@
*/
#define HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG 0x2U

/**
* @defgroup http_response_option_flags HTTPResponse_t Flags
* @brief Flags for #HTTPResponse_t.respOptionFlags.
* These flags control configurations of response parsing.
*
* Flags should be bitwise-ORed with each other to change the behavior of
* #HTTPClient_ReceiveAndParseHttpResponse and #HTTPClient_Send.
*/

/**
* @ingroup http_response_option_flags
* @brief Set this flag to indicate that the response body should not be parsed.
*
* Setting this will cause parser to stop after parsing the headers. Portion of raw body
* may be available in #HTTPResponse_t.pBody and #HTTPResponse_t.bodyLen.
*
* This flag is valid only for #HTTPResponse_t respOptionFlags parameter.
*/
#define HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG 0x1U

/**
* @ingroup http_constants
* @brief Flag that represents End of File byte in the range specification of
Expand Down Expand Up @@ -292,12 +312,22 @@ typedef enum HTTPStatus
HTTPSecurityAlertInvalidContentLength,

/**
* @brief An error occurred in the third-party parsing library.
* @brief Represents the state of the HTTP parser when it is paused.
*
* Functions that may return this value:
* - #HTTPClient_Send
* - #HTTPClient_ReadHeader
* This state indicates that the parser has encountered a pause condition and is waiting for further input.
*
* @see HTTPClient_Send
* @see HTTPClient_ReceiveAndParseHttpResponse
*/
HTTPParserPaused,

/**
* @brief An error occurred in the third-party parsing library.
*
* Functions that may return this value:
* - #HTTPClient_Send
* - #HTTPClient_ReadHeader
*/
HTTPParserInternalError,

/**
Expand Down Expand Up @@ -535,6 +565,13 @@ typedef struct HTTPResponse
*/
uint8_t areHeadersComplete;

/**
* @brief Flags to activate other response configurations.
*
* Please see @ref http_response_option_flags for more information.
*/
uint32_t respOptionFlags;

/**
* @brief Flags of useful headers found in the response.
*
Expand Down
5 changes: 5 additions & 0 deletions source/include/core_http_client_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@
*/
#define LLHTTP_STOP_PARSING HPE_USER

/**
* @brief Return value for llhttp registered callback to signal pause
*/
#define LLHTTP_PAUSE_PARSING HPE_PAUSED

/**
* @brief Return value for llhttp_t.on_headers_complete to signal
* that the HTTP response has no body and to halt further execution.
Expand Down

0 comments on commit 00677cb

Please sign in to comment.