static HTTPStatus_t parseHttpResponse()

in source/core_http_client.c [1136:1219]


static HTTPStatus_t parseHttpResponse( HTTPParsingContext_t * pParsingContext,
                                       HTTPResponse_t * pResponse,
                                       size_t parseLen )
{
    HTTPStatus_t returnStatus;
    http_parser_settings parserSettings = { 0 };
    size_t bytesParsed = 0U;
    const char * parsingStartLoc = NULL;

    /* Disable unused variable warning. */
    ( void ) bytesParsed;

    assert( pParsingContext != NULL );
    assert( pResponse != NULL );

    /* If this is the first time this parsing context is used, then set the
     * response input. */
    if( pParsingContext->pResponse == NULL )
    {
        pParsingContext->pResponse = pResponse;
        pParsingContext->pBufferCur = ( const char * ) pResponse->pBuffer;

        /* Initialize the status-code returned in the response. */
        pResponse->statusCode = 0U;
        /* Initialize the start of the response body and length. */
        pResponse->pBody = NULL;
        pResponse->bodyLen = 0U;

        /* Initialize the start of the headers, its length, and the count for
         * the parsing that follows the status. */
        pResponse->pHeaders = NULL;
        pResponse->headersLen = 0U;
        pResponse->headerCount = 0U;
        /* Initialize the response flags. */
        pResponse->respFlags = 0U;
    }
    else
    {
        /* This function is currently private to the HTTP Client library. It is
         * therefore a development bug to have this function invoked in
         * succession without the same response. */
        assert( pParsingContext->pResponse == pResponse );
    }

    /* Initialize the callbacks that http_parser_execute will invoke. */
    http_parser_settings_init( &parserSettings );
    parserSettings.on_message_begin = httpParserOnMessageBeginCallback;
    parserSettings.on_status = httpParserOnStatusCallback;
    parserSettings.on_header_field = httpParserOnHeaderFieldCallback;
    parserSettings.on_header_value = httpParserOnHeaderValueCallback;
    parserSettings.on_headers_complete = httpParserOnHeadersCompleteCallback;
    parserSettings.on_body = httpParserOnBodyCallback;
    parserSettings.on_message_complete = httpParserOnMessageCompleteCallback;

    /* Setting this allows the parsing context and response to be carried to
     * each of the callbacks that http_parser_execute() will invoke. */
    pParsingContext->httpParser.data = pParsingContext;

    /* Save the starting response buffer location to parse. This is needed to
     * ensure that we move the next location to parse to exactly how many
     * characters were parsed in this call. */
    parsingStartLoc = pParsingContext->pBufferCur;

    /* This will begin the parsing. Each of the callbacks set in
     * parserSettings will be invoked as parts of the HTTP response are
     * reached. */
    bytesParsed = http_parser_execute( &( pParsingContext->httpParser ),
                                       &parserSettings,
                                       parsingStartLoc,
                                       parseLen );

    /* The next location to parse will always be after what has already
     * been parsed. */
    pParsingContext->pBufferCur = parsingStartLoc + bytesParsed;

    LogDebug( ( "Parsed HTTP Response buffer: BytesParsed=%lu, "
                "ExpectedBytesParsed=%lu",
                ( unsigned long ) bytesParsed,
                ( unsigned long ) parseLen ) );

    returnStatus = processHttpParserError( &( pParsingContext->httpParser ) );

    return returnStatus;
}