-
Notifications
You must be signed in to change notification settings - Fork 778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use grpc-gateway with dcodeIO/protobuf.js ? #80
Comments
Those two libraries are both JavaScript implementations of Protocol Buffers, but they are completely different implementations, and they have completely different interfaces. Neither should be considered a drop-in replacement of the other. Protobuf.js has an API for constructing a specific message from a regular JavaScript object. This is probably the closest you will get to "automatic translation from js objects to protobuf messages". That is what Node gRPC uses internally. As far as I know, protobuf/js does not have such an API. |
The API you are mentioning seems to be exactly what I'm looking for, would you mind showing a code example? |
Sorry I got you wrong. I thought you meant grpc-node is using google-protobufjs, but actually it's using dcodeIO/protobuf.js. Got it, many thanks ! |
not so fast... I'd like to use protobuf.js for everything, except the HTTP call. As per their documentation:
@murgatroid99 Any chance to have a short example on how to make the call with grpc-web, but using protobuf.js for everything else? (ie: kind of the |
Current grpc-web does not have a public API for plugging in arbitrary protobuf library. So grpc-web has to be used together with protobuf/js for now. Can you brief why you prefer protobuf.js? |
I think protobuf.js main advantages are:
Finally it also supports the proto services definitions parsing, if can inject a rpcImplementation function (the one described above) I feel grpc-web could fit particularly well this use case (being agnostic toward the protobuf implementation, and being responsible to making the http call only, if that make sense). |
Can you please point me to the benchmarks? |
@sulliwane do you want to use protobuf.js just for encoding, and are looking for a pure client? We implemented a grpc-web client transport in Fetch API+XHR fallback in TypeScript (that is translateable to ES). Let us know if it is useful for you :) |
@mwitkow Yes, you got my point. I was away for a few days, so I'm just looking at your grpc-web implementation now. It looks like what I'm trying to do, except that the response you are reading seems to be already of type Uint8Array! -> But the nginx-gateway here response is a base64 encoded string (as far as I know, there is just this mode), so did you test using your grpc-web client with the nginx-gateway of this current repo? As you can see in my code sample above, I'm just trying to get a simple unary call working with fetch and the current repo nginx-gateway, my request is well formed, but I just can't decode the gateway response base64 string to a correct proto object. So I suspect the base64 string is not just a simple binary proto object encoded as base64 (I need to parse something somewhere I guess). Thank you for you help :) |
sulliwane@, the grpc-web implementation is subject to change (frequently). E.g the support of the new spec is not yet published. For the current version, we have special logic to decide when to use base64 encoding, how to apply padding, keep-alive etc. The gateway from @mwitkow is useful to test your own manual client implementation, However, we'd like to limit the adoption of the grpc-web protocol spec to only browser clients. |
@wenbozhu Ok. So you mean that this spec is not up to date right? I'm in fact trying to implement browser only client (no xhr, fetch only). By slicing out the first 2 bytes of the response, I could properly decode the grpc-gateway response. ...
.then(base64_string => {
// this is the proper way to convert base64 string to Uint8Array
const buffer = Uint8Array.from(atob(base64_string), c => c.charCodeAt(0))
const MessageRes = root.lookup("package.MessageRes");
var messageRes = MessageRes.decode(buffer.slice(2));
console.log('messageRes', messageRes) // OK, that's a proper proto message
}) I'm not clear why grpc-gateway added an outer envelope to my proto message though... |
@sulliwane the nginx gateway uses old code, that predates the protocol spec. |
It's working for grpc-web + protobuf.js. import { ChunkParser, ChunkType } from "grpc-web-client/dist/ChunkParser"
import { RPCImpl } from "protobufjs";
function rpcImpl(serviceName: string): RPCImpl {
return async (method, requestData, callback) => {
const request = await fetch(`${BASE_URL}/${serviceName}/${method.name}`, {
method: "POST",
headers: {
"content-type": "application/grpc-web+proto",
"x-grpc-web": "1",
},
body: frameRequest(requestData),
});
const buffer = await request.arrayBuffer();
const chunk = parseChunk(buffer);
callback(null, chunk && chunk.data ? new Uint8Array(chunk.data) : null);
};
}
function parseChunk(buffer: ArrayBuffer) {
return new ChunkParser()
.parse(new Uint8Array(buffer))
.find(chunk => chunk.chunkType === ChunkType.MESSAGE);
}
function frameRequest(bytes: Uint8Array) {
const frame = new ArrayBuffer(bytes.byteLength + 5);
new DataView(frame, 1, 4).setUint32(0, bytes.length, false);
new Uint8Array(frame, 5).set(bytes);
return new Uint8Array(frame);
} |
@justerest it looks like your example uses thehttps://github.com/improbable-eng/grpc-web rather than grpc/grpc-web. |
@clehene you're right. I was inattentive. |
@justerest @sulliwane note that it's possible to use both protobuf.js and google/grpc-web by converting between one and the other at binary level through an equivalent of |
Closing this for now. We are unlikely to support dynamic protobuf in the near future. |
* Fixup removed gRPC interface for metadata. * Fixup change in ServerTransport interface in gRPC. * fixup testserver for the metadata call
Getting Failed to parse URL, Browser is not able to parse the URL Fetch error: TypeError: Failed to execute 'fetch' on 'Window': Failed to parse URL from http://10.81.200.09:8000/loginService_package.LoginService/LoginMethod
|
@rmv9490 Your error message says "Fetch error: TypeError: Failed to execute 'fetch' on 'Window': Failed to parse URL from http://10.81.200.09:8000/loginService_package.LoginService/LoginMethod" So, the problem is in that URL. In that IP address, the fourth component is |
Hello,
I'm wondering how protobuf/js relates to dcodeIO/protobuf.js? Are these two lib doing the exact same thing?
Is it possible to swap protobuf/js for dcodeIO/protobuf.js?
I'm looking for a way to have an automatic translation from js objects to protobuf messages (without having to manually set every fields of the messages) that's how I do with the node-grpc implementation.
Many thanks
The text was updated successfully, but these errors were encountered: