Version
What is gRPC stream?
A gRPC stream refers to a communication channel that allows bidirectional data flow between a client and a server in real-time. It's one of the key features of gRPC and is used for various purposes, including real-time updates, event-driven communication, and efficient data streaming
We can follow the older post in here: gRPC stream vs Websocket
What is Cocos Creator?
Cocos Creator is both an efficient, lightweight, free and open source cross-platform 2D & 3D graphics engine and a real-time interactive 2D & 3D digital content creation platform. With many advantages such as High Performance, Low Power Consumption, Streaming Loading and Cross-Platform Publishing, we can use it to create projects in fields such as Games, Cars, XR, MetaVerse etc.
Problem
We are having issues using gRPC Stream in our project because it is not supported by Cocos Creator; let's take a deeper look at why this is the case.
Testing gRPC stream with Cocos Creator
Crearte streaming_test.proto
service StreamingTest {
rpc BiDirectional(stream Message) returns (stream Message);
rpc SeverStreaming(SeverStreamingRequest) returns (stream Message);
rpc ClientStreaming(stream Message) returns (ClientStreamReply);
}
message Message {
string id = 1;
bytes metadata = 2;
google.protobuf.Timestamp created_at = 3;
}
message SeverStreamingRequest {}
message ClientStreamReply {}
grpc/grpc-web
- Set up gRPC-web
- I have use gRPC-web to generate browser clients, gRPC-web clients connect to gRPC services via a special proxy; by default, gRPC-web uses Envoy.
- Install Runtime Library & Code Generator Plugin
- Generate
$ protoc -I=$DIR streaming_test.proto \
--js_out=import_style=commonjs:$OUT_DIR \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:$OUT_DIR
But... Client-side and Bi-directional streaming is not currently supported

improbable-eng/grpc-web
gRPC Web implementation for Golang and TypeScript, a custom lib forked from grpc/grpc-web
It sill not working with Cocos Creator 😞
Root cause
The issue we're facing pertains to using the "connect" method in Cocos, which is challenging due to Cocos using an older JavaScript engine that doesn't support newer APIs. grpc-web stream specifically require the Fetch API for out project.
We attempted to implement the Fetch API through XMLHttpRequest using a polyfill. While we were successful in making unary (single) method calls, we encountered difficulties with streaming. This is because XMLHttpRequest doesn't support reading a partial response body (chunk) - we must wait for the request to complete before accessing the entire body.
To fully address this issue, we would need to dive deeper into native code and create a custom implementation of the Fetch API that supports streaming. Keep in mind that this is our experience with Android, and we would need to separately implement and test for iOS.
It's also worth noting that the grpc-web library faces a similar limitation as it uses XMLHttpRequest, it is unable to perform asynchronous operations, which could be the reason it doesn't fully support streaming.
- https://github.com/cocos/cocos-engine/blob/develop/native/cocos/bindings/manual/jsb_xmlhttprequest.cpp
- https://github.com/cocos/cocos-engine/blob/develop/native/cocos/network/HttpClient-java.cpp#L280-L304
- https://github.com/cocos/cocos-engine/blob/develop/native/cocos/platform/android/java/src/com/cocos/lib/CocosHttpURLConnection.java#L262-L300
Therefore... we use websocket instead 😁

