static int s_on_incoming_header_block_done()

in source/http_stream.c [69:145]


static int s_on_incoming_header_block_done(
    struct aws_http_stream *native_stream,
    enum aws_http_header_block header_block,
    void *user_data) {
    struct http_stream_binding *stream = user_data;

    int response_code = 0;
    if (aws_http_stream_get_incoming_response_status(native_stream, &response_code)) {
        return AWS_OP_ERR;
    }

    if (stream->received_headers_count > PY_SSIZE_T_MAX) {
        return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
    }
    Py_ssize_t num_headers = (Py_ssize_t)stream->received_headers_count;

    int aws_result = AWS_OP_SUCCESS;

    /*************** GIL ACQUIRE ***************/
    PyGILState_STATE state;
    if (aws_py_gilstate_ensure(&state)) {
        return AWS_OP_ERR; /* Python has shut down. Nothing matters anymore, but don't crash */
    }

    /* Build up a list of (name,value) tuples,
     * extracting values from buffer of [name,value,name,value,...] null-terminated strings */
    PyObject *header_list = PyList_New(num_headers);
    if (!header_list) {
        aws_result = aws_py_raise_error();
        goto done;
    }

    struct aws_byte_cursor string_cursor = aws_byte_cursor_from_buf(&stream->received_headers);

    for (Py_ssize_t i = 0; i < num_headers; ++i) {
        const char *name_str = (const char *)string_cursor.ptr;
        size_t name_len = strlen((const char *)string_cursor.ptr);

        aws_byte_cursor_advance(&string_cursor, name_len + 1);

        const char *value_str = (const char *)string_cursor.ptr;
        size_t value_len = strlen((const char *)string_cursor.ptr);

        aws_byte_cursor_advance(&string_cursor, value_len + 1);

        PyObject *tuple = Py_BuildValue("(s#s#)", name_str, name_len, value_str, value_len);
        if (!tuple) {
            aws_result = aws_py_raise_error();
            goto done;
        }

        PyList_SET_ITEM(header_list, i, tuple); /* steals reference to tuple */
    }

    /* TODO: handle informational and trailing headers */
    if (header_block == AWS_HTTP_HEADER_BLOCK_MAIN) {

        /* Deliver the built up list of (name,value) tuples */
        PyObject *result = PyObject_CallMethod(stream->self_proxy, "_on_response", "(iO)", response_code, header_list);
        if (!result) {
            aws_result = aws_py_raise_error();
            goto done;
        }
        Py_DECREF(result);
    }

    /* Clear the buffer so we're ready for next header block */
    stream->received_headers.len = 0;
    stream->received_headers_count = 0;

done:
    Py_XDECREF(header_list);
    PyGILState_Release(state);
    /*************** GIL RELEASE ***************/

    return aws_result;
}