purerpc icon indicating copy to clipboard operation
purerpc copied to clipboard

Give access to request headers and ability to respond with custom headers

Open standy66 opened this issue 5 years ago • 4 comments

Need to address 4 use cases:

  1. Client wants to send additional request headers to server
  2. Client wants to read all of the response headers or trailers
  3. Server wants to read all of the request headers
  4. 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.

standy66 avatar Jul 26 '18 08:07 standy66

Trying to address this in #8

standy66 avatar Nov 11 '18 22:11 standy66

#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

standy66 avatar Jan 25 '19 22:01 standy66

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)

standy66 avatar Jan 25 '19 22:01 standy66

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.

standy66 avatar Jan 25 '19 23:01 standy66