purerpc
purerpc copied to clipboard
Give access to request headers and ability to respond with custom headers
Need to address 4 use cases:
- Client wants to send additional request headers to server
- Client wants to read all of the response headers or trailers
- Server wants to read all of the request headers
- Server wants to send additional response headers or trailers to client
In gRPC, methods differ by cardinality: request may be either unary in both ways (UNARY_UNARY), client-side streaming (STREAM_UNARY), server-side streaming (UNARY_STREAM) and bidirectional streaming (STREAM_STREAM). Keeping that in mind, some cases listed above are far more difficult to design than the others.
Trying to address this in #8
#8 got merged and addressed two simpler cases: 1st and 3rd. Clients can now send additional request headers with metadata
keyword only argument:
stub.SayHello(request, metadata=(("x-api-key", "QWERTY"), ("x-request-id", "some-id")))
RPC handlers can get access to request metadata via optional last request
argument:
async def SayHello(self, message, request):
print("Server received metadata", request.custom_metadata)
return HelloReply(message=base64.b64encode(pickle.dumps(request.custom_metadata)))
See more usage cases in unit tests
Actually now that I think of it, it may be better to change optional argument name to something like context
or request_info
, to separate it from request message that arrived in handler (first argument in the example code above)
Still 2nd and 4th case remain unimplemented. Here is some thoughts:
We can make two new yieldables: Headers and Trailers. Then we make socket to wait initiating response until either object of type Headers or first message is yielded. Similarly, the connection is closed on either Trailers or only after handler exits. The problem is that RPC cardinality is no longer tied to the function type: it can either by async generator or async function in both cases (multiple streaming response messages or just a single message). That's when it comes to server responding with custom headers/trailers.
For client reading headers/trailers it's different. I am yet to discover a way that works with async generators and is optional in a way that all existing code that does not check headers/trailers continues to work as expected.