static HTTPStatus_t findHeaderInResponse()

in source/core_http_client.c [2384:2496]


static HTTPStatus_t findHeaderInResponse( const uint8_t * pBuffer,
                                          size_t bufferLen,
                                          const char * pField,
                                          size_t fieldLen,
                                          const char ** pValueLoc,
                                          size_t * pValueLen )
{
    HTTPStatus_t returnStatus = HTTPSuccess;
    http_parser parser = { 0 };
    http_parser_settings parserSettings = { 0 };
    findHeaderContext_t context = { 0 };
    size_t numOfBytesParsed = 0U;

    context.pField = pField;
    context.fieldLen = fieldLen;
    context.pValueLoc = pValueLoc;
    context.pValueLen = pValueLen;
    context.fieldFound = 0U;
    context.valueFound = 0U;

    /* Disable unused variable warning. This variable is used only in logging. */
    ( void ) numOfBytesParsed;

    http_parser_init( &parser, HTTP_RESPONSE );

    /* Set the context for the parser. */
    parser.data = &context;

    /* The intention here to define callbacks just for searching the headers. We will
     * need to create a private context in httpParser->data that has the field and
     * value to update and pass back. */
    http_parser_settings_init( &parserSettings );
    parserSettings.on_header_field = findHeaderFieldParserCallback;
    parserSettings.on_header_value = findHeaderValueParserCallback;
    parserSettings.on_headers_complete = findHeaderOnHeaderCompleteCallback;

    /* Start parsing for the header! */
    numOfBytesParsed = http_parser_execute( &parser,
                                            &parserSettings,
                                            ( const char * ) pBuffer,
                                            bufferLen );

    LogDebug( ( "Parsed response for header search: NumBytesParsed=%lu",
                ( unsigned long ) numOfBytesParsed ) );

    if( context.fieldFound == 0U )
    {
        /* If header field is not found, then both the flags should be zero. */
        assert( context.valueFound == 0U );

        /* Header is not present in buffer. */
        LogWarn( ( "Header not found in response buffer: RequestedHeader=%.*s",
                   ( int ) fieldLen,
                   pField ) );

        returnStatus = HTTPHeaderNotFound;
    }
    else if( context.valueFound == 0U )
    {
        /* The response buffer is invalid as only the header field was found
         * in the "<field>: <value>\r\n" format of an HTTP header. */
        LogError( ( "Unable to find header value in response: "
                    "Response data is invalid: "
                    "RequestedHeader=%.*s, ParserError=%s",
                    ( int ) fieldLen,
                    pField,
                    http_errno_description( HTTP_PARSER_ERRNO( &( parser ) ) ) ) );
        returnStatus = HTTPInvalidResponse;
    }
    else
    {
        /* Header is found. */
        assert( ( context.fieldFound == 1U ) && ( context.valueFound == 1U ) );

        LogDebug( ( "Found requested header in response: "
                    "HeaderName=%.*s, HeaderValue=%.*s",
                    ( int ) fieldLen,
                    pField,
                    ( int ) ( *pValueLen ),
                    *pValueLoc ) );
        returnStatus = HTTPSuccess;
    }

    /* If the header field-value pair is found in response, then the return
     * value of "on_header_value" callback (related to the header value) should
     * cause the http_parser.http_errno to be "CB_header_value". */
    if( ( returnStatus == HTTPSuccess ) &&
        ( parser.http_errno != ( unsigned int ) HPE_CB_header_value ) )
    {
        LogError( ( "Header found in response but http-parser returned error: "
                    "ParserError=%s",
                    http_errno_description( HTTP_PARSER_ERRNO( &( parser ) ) ) ) );
        returnStatus = HTTPParserInternalError;
    }

    /* If header was not found, then the "on_header_complete" callback is
     * expected to be called which should cause the http_parser.http_errno to be
     * "OK" */
    else if( ( returnStatus == HTTPHeaderNotFound ) &&
             ( parser.http_errno != ( unsigned int ) ( HPE_OK ) ) )
    {
        LogError( ( "Header not found in response: http-parser returned error: "
                    "ParserError=%s",
                    http_errno_description( HTTP_PARSER_ERRNO( &( parser ) ) ) ) );
        returnStatus = HTTPInvalidResponse;
    }
    else
    {
        /* Empty else for MISRA 15.7 compliance. */
    }

    return returnStatus;
}