Async Insecure Client
When using the InsecureClient it does not correctly create async channel. After establishing a channel with fake_credentials the following code defaults to using a sync connection:
insecure_channel = grpc.insecure_channel(target, options, compression)
The class method create_channel switches automatically between grpc. and grpc.aio. Should this behaviour also apply in the insecure client?
async def rr():
client = Client(
"localhost:50051",
insecure_bearer_token_credentials("123")
)
post_one = ObjectReference(object_type="org/brief", object_id="1")
emilia = SubjectReference(object=ObjectReference(
object_type="org/tag/user",
object_id="emilia",
))
resp = await client.CheckPermission(CheckPermissionRequest(
resource=post_one,
permission="viewer",
subject=emilia,
))
assert resp.permissionship != CheckPermissionResponse.PERMISSIONSHIP_HAS_PERMISSION
# force async loop
asyncio.run(rr())
The above works as expected
Running the same but with:
client = InsecureClient(
"localhost:50051",
"123"
)
results in:
TypeError: object CheckPermissionResponse can't be used in 'await' expression
I'll have a look at this.
I've got a PR in progress... the python gRPC client makes this a pain.
Related to https://github.com/grpc/grpc/issues/33618
This code helped for me
class BaseAuthInterceptor:
def __init__(self, token: str):
self._token = token
def _add_auth(self, client_call_details):
metadata = list(client_call_details.metadata or [])
metadata.append(("authorization", f"Bearer {self._token}"))
return grpc.aio.ClientCallDetails(
method=client_call_details.method,
timeout=client_call_details.timeout,
metadata=metadata,
credentials=client_call_details.credentials,
wait_for_ready=client_call_details.wait_for_ready,
)
class AsyncAuthUnaryUnaryInterceptor(
BaseAuthInterceptor,
grpc.aio.UnaryUnaryClientInterceptor,
):
async def intercept_unary_unary(self, continuation, client_call_details, request):
return await continuation(self._add_auth(client_call_details), request)
class AsyncAuthUnaryStreamInterceptor(
BaseAuthInterceptor,
grpc.aio.UnaryStreamClientInterceptor,
):
async def intercept_unary_stream(self, continuation, client_call_details, request):
return await continuation(self._add_auth(client_call_details), request)
class AsyncAuthStreamUnaryInterceptor(
BaseAuthInterceptor,
grpc.aio.StreamUnaryClientInterceptor,
):
async def intercept_stream_unary(self, continuation, client_call_details, request_iterator):
return await continuation(self._add_auth(client_call_details), request_iterator)
class AsyncAuthStreamStreamInterceptor(
BaseAuthInterceptor,
grpc.aio.StreamStreamClientInterceptor,
):
async def intercept_stream_stream(self, continuation, client_call_details, request_iterator):
return await continuation(self._add_auth(client_call_details), request_iterator)
class AsyncInsecureClient(Client):
def __init__(self, target: str, token: str, options=None, compression=None):
channel = grpc.aio.insecure_channel(
target,
options,
compression,
[
AsyncAuthUnaryUnaryInterceptor(token),
AsyncAuthUnaryStreamInterceptor(token),
AsyncAuthStreamUnaryInterceptor(token),
AsyncAuthStreamStreamInterceptor(token),
],
)
self.init_stubs(channel)
Created this with chatgpt and not tested much, but in my scenario it is working
+1 for @pavel7002007 solution