Skip to content

Cannot proxy requests? #294

Open
Open
@Zentren

Description

@Zentren

Is it not possible to proxy-chain requests returning (at least) struct responses?

i.e. client <=> proxy.rpc() <=> server.rpc()

Please see attached test code to better understand issue and reproduce. Commented-out lines from line 22 can be uncommented separately to investigate (not-so-different) outcomes. Either an exception is raised, or default values for fields are returned.

Test code

test.py

from unittest import result
import capnp
import socket

import test_capnp


class Test(test_capnp.Test.Server):

    def getResult(self, **kwargs):
        return test_capnp.Result.new_message(value=1)


class TestProxy(test_capnp.Test.Server):

    def __init__(self, test):
        self._test = test

    def getResult(self, **kwargs):
        return self._test.getResult()  # remote exception: <class 'AttributeError'>:'NoneType' object has no attribute 'type'

        # return self._test.getResult().result  # remote exception: <class 'AttributeError'>:'NoneType' object has no attribute 'type'

        # return self._test.getResult().then(lambda response: {"value": 1})
        
        # return self._test.getResult().then(
        #     lambda _: test_capnp.Result.new_message(value=1),
        #     error_func=lambda error: print(error),
        # )

        # return self._test.getResult().then(
        #     lambda response: self._copy_response_result(response),
        #     error_func=lambda error: print(error),
        # )

        # return self._test.getResult().then(
        #     lambda response: self._copy_response_result_as_builder(response),
        #     error_func=lambda error: print(error),
        # )

        # return self._test.getResult().then(
        #     lambda response: self._reuse_response(response),
        #     error_func=lambda error: print(error),
        # )

    def _reuse_response(self, response):
        print("Server result value: " + str(response.result.value))
        return response

    def _copy_response_result(self, response):
        print("Server result value: " + str(response.result.value))
        return test_capnp.Result.new_message(value=response.result.value)

    def _copy_response_result_as_builder(self, response):
        print("Server result value: " + str(response.result.value))
        return response.result.as_builder()


def test():
    principal_server_sock, principal_client_sock = socket.socketpair(socket.AF_UNIX)

    principal_server = capnp.TwoPartyServer(principal_server_sock, bootstrap=Test())
    principal_client = capnp.TwoPartyClient(principal_client_sock)

    proxy_server_sock, proxy_client_sock = socket.socketpair(socket.AF_UNIX)

    proxy = TestProxy(principal_client.bootstrap().cast_as(test_capnp.Test))
    proxy_server = capnp.TwoPartyServer(proxy_server_sock, bootstrap=proxy)
    proxy_client = capnp.TwoPartyClient(proxy_client_sock)

    test_client = proxy_client.bootstrap().cast_as(test_capnp.Test)
    
    result = test_client.getResult().wait().result

    print("Proxy result: " + str(result))
    assert result.value == 1


if __name__ == "__main__":
    test()

test.capnp

@0xc5358bd118c9ee3a;

struct Result {
    value @0 :Int32;
}

interface Test {
    getResult @0 () -> (result :Result);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions