Search code examples
javascriptpythonenvoyproxygrpc-web

How to send trailing metadata from python gRPC service to grpc-web client?


I'm trying to send trailing metadata from python gRPC service to grpc-web client. But on client side I cannot receive it.

I'm using envoy proxy server to connect grpc-web with python gRPC service.

For sending metadata I'm using this method:

class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        context.set_trailing_metadata((
            ('checksum', 'I agree'),
            ('retry', 'false'),
        ))
        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)

On client I'm trying to access metadata this way:

var call = greeterService.sayHello(request, {}, function(err, response) {
  if (err) {
    console.log(err.code);
    console.log(err.message);
  } else {
    console.log(response.getMessage());
  }
});
call.on('status', function(status) {
  console.log(status.code);
  console.log(status.details);
  console.log(status.metadata); // here should arrive metadata
});

I'm sending it how it is described in documentation. But metadata is not arrived.

Did anybody have such problem?


Solution

  • Before calling method set_trailing_metadata, you need to call send_initial_metadata with same medatdata keys but any values.

    In my case it will looks like this:

    class Greeter(helloworld_pb2_grpc.GreeterServicer):
        def SayHello(self, request, context):
            context.send_initial_metadata((
                ('checksum', ''),
                ('retry', ''),
            ))
            context.set_trailing_metadata((
                ('checksum', 'I agree'),
                ('retry', 'false'),
            ))
            return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
    

    Actually I found this solution accidentally.

    I assume that you need to specify headers names in initial metadata and only then you should set headers values in trailing metadata and then envoy could pack it properly and deliver via HTTP 1.1.