grpc / grpc/grpc-node

Package path ignored in static gRPC server generation

Open
#1,326 2 comments 0 reactions 0 assignees View on GitHub
package: grpc-tools
Dominant language
TypeScript
Stars
4.8k
Forks
716
Avg merge
2d 3h
Merged PRs (30d)
10

Description

### Problem description

The gRPC statically generated code I am receiving crashes on `undefined` in request unmarshalling because the generated gRPC method for deserializing request messages in the `_grpc_pb.js` is not interpreting the package structure the same way that the generated protobuf code in the `_pb.js` did for the message type.

In short, I'm getting this method in `library_api_grpc_pb`:
```
function deserialize_com_rcbrown_grpc_v1_GetBooksRequest(buffer_arg) {
return com_rcbrown_grpc_v1_library_api_pb.GetBooksRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
```

But this binding in `library_api_pb`:
```
goog.exportSymbol('com.rcbrown.grpc.v1.GetBooksRequest', null, proto);
```

I confirmed in the debugger that the exported `com_rcbrown_grpc_v1_library_api_pb` contains deep object nesting to match that. So the deserialize method should have used `com_rcbrown_grpc_v1_library_api_pb.com.rcbrown.grpc.v1.GetBooksRequest`. As is, `GetBooksRequest` does not exist at the top level of `com_rcbrown_grpc_v1_library_api_pb`, so the call fails with `TypeError: Cannot read property 'deserializeBinary' of undefined`.

Is this because of "If you are using CommonJS-style imports, any package declarations in your .proto files are ignored by the compiler" mentioned [here](https://developers.google.com/protocol-buffers/docs/reference/javascript-generated)? I hope not, because it makes the [Uber v2](https://github.com/uber/prototool/blob/dev/style/README.md#directory-structure) recommended style unusable in JavaScript with static generation.

More detail:

My project is structured like this:
```
proto/
com/
rcbrown/
grpc/
v1/
library_api.proto
library_book.proto
static/
server/
generated/
package.json
```

The proto file looks like:
```proto3
// library_api.proto

syntax = "proto3";

package com.rcbrown.grpc.v1;

import "com/rcbrown/grpc/v1/library_book.proto";

// A minimal sample API that a library might present.
service LibraryAPI {
// Retrieves all of the books in the library.
rpc GetBooks(GetBooksRequest) returns (GetBooksResponse);
}

message GetBooksRequest {
// No parameters needed; all books are returned
}

message GetBooksResponse {
repeated LibraryBook library_books = 1;
}
```

In `package.json`, I am running the following:
```
grpc_tools_node_protoc \
--proto_path=../../proto \
--js_out=import_style=commonjs_strict,binary:generated \
--grpc_out=generated ../../proto/com/rcbrown/grpc/v1/*.proto
```

### Reproduction steps
[My repository](https://github.com/rcbrown/grpc-node-examples/tree/static) demonstrates the problem (branch `static`).
1. Clone the repo.
1. `cd static/server`
1. `npm install`
1. `npm run start`
1. Use a gRPC client to call `GetBooks`. Failure occurs in request deserialization.

### Environment
- MacOs Catalina 10.15.3 `Darwin 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan 9 20:58:23 PST 2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64`
- Node version `v12.16.1`
- Node installation method `nvm`
- If applicable, compiler version N/A
- Package name and version grpc@1.24.2, google-protobuf@3.11.4, grpc-tools@1.8.1

### Additional context
`library_book.proto` is mentioned in the code I linked. I didn't include it above because the failure stems entirely from types defined in `library_api.proto`, but here it is for completeness:
```
// library_book.proto

syntax = "proto3";

package com.rcbrown.grpc.v1;

// Indicates whether or not the library book is checked out.
enum CheckoutStatus {
CHECKOUT_STATUS_INVALID = 0;
CHECKOUT_STATUS_IN = 1;
CHECKOUT_STATUS_OUT = 2;
}

// A book, to read and enjoy.
message LibraryBook {
string title = 1;
string author = 2;
CheckoutStatus checkout_status = 3;
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.