Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sonora/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ async def _do_unary_response(
else:
message_data = b""

trailers = [(b"grpc-status", str(context.code.value[0]).encode())]
trailers = [("grpc-status", str(context.code.value[0]))]

if context.details:
trailers.append(
(b"grpc-message", quote(context.details.encode("utf8")).encode("ascii"))
("grpc-message", quote(context.details.encode("utf8")))
)

if context._trailing_metadata:
Expand Down
8 changes: 8 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ def HelloStreamMetadata(self, request, context):

class AsyncGreeter(helloworld_pb2_grpc.GreeterServicer):
async def SayHello(self, request, context):
if request.HasField("response_status"):
context.set_code(request.response_status.code)
context.set_details(request.response_status.message)

return helloworld_pb2.HelloReply(message=FORMAT_STRING.format(request=request))

async def SayHelloSlowly(self, request, context):
Expand All @@ -93,6 +97,10 @@ async def SayHelloSlowly(self, request, context):
for char in message:
yield helloworld_pb2.HelloReply(message=char)

if request.HasField("response_status"):
context.set_code(request.response_status.code)
context.set_details(request.response_status.message)

async def Abort(self, request, context):
await context.abort(grpc.StatusCode.ABORTED, "test aborting")

Expand Down
10 changes: 10 additions & 0 deletions tests/protos/tests/helloworld.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,19 @@ service Greeter {
rpc StreamTimeout(TimeoutRequest) returns (stream google.protobuf.Empty) {}
}

// A protobuf representation for grpc status. This is used by test
// clients to specify a status that the server should attempt to return.
message EchoStatus {
int32 code = 1;
string message = 2;
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;

// Status to set at the end of the RPC.
EchoStatus response_status = 2;
}

// The response message containing the greetings
Expand Down
65 changes: 65 additions & 0 deletions tests/test_asgi_helloworld.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,71 @@ async def test_helloworld_unary_metadata_binary(asgi_greeter):
assert dict(trailing_metadata)["trailing-metadata-key-bin"] == repr(b"\0\1\2\3")


@pytest.mark.asyncio
async def test_unary_trailing_status_no_message(asgi_greeter):
for name in ("you", "world"):
request = helloworld_pb2.HelloRequest(name=name)
call = asgi_greeter.SayHello(request)
_response = await call

trailers = dict(await call.trailing_metadata())
assert "grpc-status" in trailers
assert trailers["grpc-status"] == "0"
assert "grpc-message" not in trailers


@pytest.mark.asyncio
async def test_unary_trailing_status_message(asgi_greeter):
print(helloworld_pb2.__file__)
for name in ("you", "world"):
request = helloworld_pb2.HelloRequest(
response_status=helloworld_pb2.EchoStatus(
code=grpc.StatusCode.OK.value[0],
message="OK",
)
)
call = asgi_greeter.SayHello(request)
_response = await call

trailers = dict(await call.trailing_metadata())
assert "grpc-status" in trailers
assert trailers["grpc-status"] == "0"
assert trailers["grpc-message"] == "OK"


@pytest.mark.asyncio
async def test_streaming_trailing_status_no_message(asgi_greeter):
for name in ("you", "world"):
request = helloworld_pb2.HelloRequest(name=name)
call = asgi_greeter.SayHelloSlowly(request)
async for _response in call:
pass

trailers = dict(await call.trailing_metadata())
assert "grpc-status" in trailers
assert trailers["grpc-status"] == "0"
assert "grpc-message" not in trailers


@pytest.mark.asyncio
async def test_streaming_trailing_status_message(asgi_greeter):
for name in ("you", "world"):
request = helloworld_pb2.HelloRequest(
response_status=helloworld_pb2.EchoStatus(
code=grpc.StatusCode.OK.value[0],
message="OK",
)
)
call = asgi_greeter.SayHelloSlowly(request)
async for _response in call:
pass

trailers = dict(await call.trailing_metadata())
assert "grpc-status" in trailers
assert trailers["grpc-status"] == "0"
assert trailers["grpc-message"] == "OK"


@pytest.mark.asyncio
async def test_helloworld_stream_metadata_ascii(asgi_greeter):
request = helloworld_pb2.HelloRequest(name="metadata-key")
Expand Down