4

I'm able to send requests to one of our gRPC-enabled, reflection-enabled server using grpcurl with the following syntax:

grpcurl --plaintext -d '{"test_input": "Test 1 2 3", "config": { "max_results": 3 }}' localhost:6565 myorg.myproject.v1alpha6.MyService.MyStub

This does not require knowledge of the protos from grpcurl. And it's just perfect because I'm using it in a test script that I want to keep as simple as possible.

I've been able to leverage that to write a very simple python script:

import json
import subprocess

input = { "test_input": "Test 1 2 3", "config": { "max_results": 3 } }
result = subprocess.check_output(['grpcurl', '--plaintext', '-d', json.dumps(input), 'localhost:6565', 'MyStub'])
dict_result = json.loads(result)

But I'm not too happy about having to call an external process.

All the documentations I found on the internet require downloading the protos and their dependencies and compile them using protoc. I can do that and this is not the object of the question. The goal here it to use Python to exchange with the server using JSON and without downloading the proto. Just like it's done with grpcurl.

Can this be done using python only ?

Coyotwill
  • 420
  • 6
  • 13

2 Answers2

1

I think not because (the excellent) gRPCurl does not appear to provide an API|SDK that you'd want to be able to script it from Python.

As you note, this only works (without a proto or protoset) on gRPC servers that support reflection.

I think your approach of controlling gRPCurl through a shell is probably the best way. It may be worth a feature request to see whether others would like to drive gRPCurl as a test harness; it could be interesting.

Alternatively, if you're not wedded to gRPCurl, there may be other tools that support reflection that can be scrpted by Python. See:

https://github.com/grpc-ecosystem/awesome-grpc#tools-test

DazWilkin
  • 32,823
  • 5
  • 47
  • 88
0

gRPC uses HTTP2 in the transport layer. Just like any other RPC framework, it runs an http server which can be queried with basic http post requests. You can basically uses requests package to trigger a POST request to the gRPC server

import requests, json

payload = { "test_input": "Test 1 2 3", "config": { "max_results": 3 } }
response = requests.post("http://localhost:6565", data=json.dumps(payload))
  • 1
    why using `data=` instead of `json=` while requests module supports it? – Sinan Cetinkaya Apr 26 '21 at 17:41
  • the code sends stringified version of the json, as you can see with json.dumps statement – Shabahat M. Ayubi Apr 26 '21 at 17:49
  • 2
    so does `json=`. `Instead of encoding the dict yourself, you can also pass it directly using the json parameter (added in version 2.4.2) and it will be encoded automatically:` https://docs.python-requests.org/en/master/user/quickstart/#more-complicated-post-requests – Sinan Cetinkaya Apr 26 '21 at 20:36
  • @ShabahatM.Ayubi I'd like to Give it a try. But then where does the rpc Method name goes ? In my example it's `myorg.myproject.v1alpha6.MyService.MyStub` – Coyotwill Jun 10 '21 at 16:10
  • @Coyotwill the final URL is composed as host/service/method, so in your case it will be: `http://localhost:6565/myorg.myproject.v1alpha6.MyService/MyStub` – Philip Patrick May 02 '23 at 11:59