Istio + Envoy grpc_json_transcoder_filter

Hi folks,

I’m trying to configure Istio + Envoy with grpc_json_transcoder_filter.

My gRPC calls are being correctly processed, however, my rest calls are not working as expected.

Does anybody know how to configure Istio with a custom envoy configuration? I had success using just Envoy (without Istio) but when I try to use both I don’t have success.

Ref:


https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/grpc_json_transcoder_filter

1 Like

is there any update?

So many issues here I am beginning to think better to just use http-grpc bridge.

I will try very soon. Let me know also if you find anything out.

1 Like

Here is the solution for using http-grpc bridge:

create an EnvoyFilter

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: echo-filtering
spec:
workloadLabels:
app: echo
filters:
- listenerMatch:
portNumber: 9009
listenerType: SIDECAR_INBOUND
insertPosition:
index: BEFORE
relativeTo: envoy.router
filterName: envoy.grpc_http1_bridge
filterType: HTTP
filterConfig:
services:
- com.test.echo.EchoService

Then access as shown below:

5 byte header. first byte zero and then 4 bytes bigindian for length.

Note the code below is scrollable:

public static void echoHttpTest() throws java.io.IOException {

System.out.println("echoHttpTest");

CloseableHttpClient httpClient = HttpClients.createDefault();

HttpPost postRequest = new HttpPost("http://10.10.10.10:” + "31380" + "/com.test.EchoService/echo");

//Set the API media type in http content-type header
postRequest.addHeader("content-type", "application/grpc");

String message = "hello";
byte[] zeroByte = {0};
byte[] messageBytes = EchoRequest
        .newBuilder()
        .setMessage(message)
        .build()
        .toByteArray();

byte[] lengthBytes = ByteBuffer.allocate(4).putInt(messageBytes.length).array();

ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(zeroByte);
baos.write(lengthBytes);
baos.write(messageBytes);

ByteArrayEntity bae = new ByteArrayEntity(baos.toByteArray());
postRequest.setEntity(bae);

//Send the request; It will immediately return the response in HttpResponse object if any
HttpResponse response = httpClient.execute(postRequest);

int statusCode = response.getStatusLine().getStatusCode();
if (statusCode >= 300) {
    throw new RuntimeException("Failed with HTTP error code : " + statusCode);
}

Header statusHeader = response.getFirstHeader("grpc-status");
System.out.println("grpc-status: " + (statusHeader != null ? statusHeader.getValue() : "n/a"));
Header msgHeader = response.getFirstHeader("grpc-message");
System.out.println("grpc-messsage: " + (msgHeader != null ? msgHeader.getValue() : "n/a"));

System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(response.getLastHeader("Content-Encoding"));
System.out.println(response.getLastHeader("Content-Length"));
System.out.println("----------------------------------------");

HttpEntity entity = response.getEntity();


//HttpEntity entity = response.getEntity();
InputStream in = entity.getContent();

ByteBuffer header = ByteBuffer.allocate(5);
System.out.println("header ");
int n =0;
try {
    n = in.read(header.array());
} catch(Exception e) {
    System.out.println(e.getMessage());
}

if (n != 5) {
    System.out.println("n="+n);
    throw new RuntimeException("expected 5 bytes, got " + n);
}
if (header.get(0) != 0) {
    throw new RuntimeException("unexpected compressed payload");
}
int size = header.getInt(1);

ByteBuffer payload = ByteBuffer.allocate(size);
n = in.read(payload.array());
if (n != size) {
    throw new RuntimeException("expected " + size + " bytes, got " + n);
}

EchoResponse echoResponse = EchoResponse.parseFrom(payload.array());
System.out.println("HTTP: " + echoResponse.getMessage());

httpClient.getConnectionManager().shutdown();

}

You want grpc-code: 0 which is success. And grpc-message is another header. My grpc server is grpc-java and it gzip encodes the grpc-code on success. Otherwise on error I grpc-code appearing in the header along with message.

I consider the bridge to be the most stable way to access grpc over http. It is used internally at Lyft as their preferred way to surface grpc service to clients over http

1 Like