siderolabs/grpc-proxy

Is there a way to proxy based on message payload?

fschoell opened this issue · 2 comments

Is there a way to access the message payload in the director? I'm trying to implement a GRPC proxy that choses a backend based on the request payload we get from the client. Basically something like this, example service:

service HelloService {
  rpc SayHello (HelloRequest) returns (stream HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

And the director should now chose the backend based on the greeting request parameter, something like this:

func Director(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) {
  // ....
  if len(request.greeting) > getCurrentThreshold() {
    return ctx, grpc.DialContext(ctx, "api-service.staging.svc.local")
  } else {
    return ctx, grpc.DialContext(ctx, "api-service.prod.svc.local")
  }
  //...
}

However as the director is only getting the context and the fullMethodName, is there any way to get the payload there? Or do you have any idea on how to implement this?

smira commented

I don't think this is technically possible. gRPC request is always a stream of messages (for unary requests, stream consists of a single message), and proxy code sets up the outgoing connection before the message is read, so it can't direct based on the payload.

I would suggest to direct based on the gRPC metadata (headers) which is available via the context.

That's what I thought, thanks for the quick response.