当我从 Flutter 应用程序向 gRPC 端点发出请求时,我得到 gRPC Invalid UTF-8

I get gRPC Invalid UTF-8 when I make a request to gRPC endpoint from Flutter app

我正在尝试将 Flutter 应用程序连接到 gRPC 服务器。 它曾经在我的旧笔记本电脑上运行良好,但现在当我尝试向端点发出请求时总是出现此错误:

gRPC Error (code: 13, codeName: INTERNAL, message: grpc: error unmarshalling request: string field contains invalid UTF-8, details: [], rawResponse: null)

当我使用另一个gRPC客户端,比如bloomRPC,调用成功,得到了正确的数据。 Flutter 应用程序调用甚至没有到达端点服务(我在那里放了一个 println 来测试它,当我从 Flutter 应用程序调用时它不打印任何东西,但它在使用 bloomRPC 时打印它)。

这是我的客户端连接代码:

class GrpcClient {
  late ClientChannel client;
  static final GrpcClient _connection = GrpcClient._connect();

  factory GrpcClient() => _connection;
  
  GrpcClient._connect(){
    client = ClientChannel(
     "10.0.2.2",
      port: 8080,
      options: ChannelOptions(credentials: ChannelCredentials.insecure(), connectionTimeout:Duration(seconds: 10))
    );

  }
}

我运行服务器用GODEBUG=http2debug=2 go run .。当我从 Bloom 拨打电话时,我得到了这个输出:

2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote SETTINGS len=6, settings: MAX_FRAME_SIZE=16384
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read SETTINGS len=36, settings: ENABLE_PUSH=0, MAX_CONCURRENT_STREAMS=0, INITIAL_WINDOW_SIZE=4194304, MAX_FRAME_SIZE=4194304, MAX_HEADER_LIST_SIZE=8192, UNKNOWN_SETTING_65027=1
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read WINDOW_UPDATE len=4 (conn) incr=4128769
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote SETTINGS flags=ACK len=0
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read HEADERS flags=END_HEADERS stream=1 len=259
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2021/12/27 22:23:52 http2: decoded hpack field header field ":scheme" = "http"
2021/12/27 22:23:52 http2: decoded hpack field header field ":method" = "POST"
2021/12/27 22:23:52 http2: decoded hpack field header field ":authority" = "localhost:8080"
2021/12/27 22:23:52 http2: decoded hpack field header field ":path" = "/protofiles.UserService/GetUserById"
2021/12/27 22:23:52 http2: decoded hpack field header field "te" = "trailers"
2021/12/27 22:23:52 http2: decoded hpack field header field "content-type" = "application/grpc"
2021/12/27 22:23:52 http2: decoded hpack field header field "user-agent" = "grpc-node/1.24.7 grpc-c/8.0.0 (windows; chttp2; ganges)"
2021/12/27 22:23:52 http2: decoded hpack field header field "grpc-accept-encoding" = "identity,deflate,gzip"
2021/12/27 22:23:52 http2: decoded hpack field header field "accept-encoding" = "identity,gzip"
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read WINDOW_UPDATE stream=1 len=4 incr=5
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read DATA flags=END_STREAM stream=1 len=122 data="\x00\x00\x00\x00u\ns\b\x05\x12\x05Hello\x1abcc4186-3a63-4a22-8dac-c144d6d0eb49\"\x05Hello*\x05Hello0\x00:\x04\b\x14\x10\nB\x05HelloJ\x05HelloR\x04\b\x14\x10\nZ\b\b\x14\x10\x01\x18\x01 \x00`\x14h\x14p\x14x\x14\x82\x01\"
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read WINDOW_UPDATE len=4 (conn) incr=5
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote WINDOW_UPDATE len=4 (conn) incr=122
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote PING len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read PING flags=ACK len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: read SETTINGS flags=ACK len=0
Hello
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote HEADERS flags=END_HEADERS stream=1 len=14
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote DATA stream=1 len=192 data="\x00\x00\x00\x00\xbb\n\xb8\x01\b\x05\x12\tHajjivsky
2021/12/27 22:23:52 http2: Framer 0xc0000a6000: wrote HEADERS flags=END_STREAM|END_HEADERS stream=1 len=24

Dart 应用程序的输出:

2021/12/27 22:25:25 http2: Framer 0xc0002b2000: wrote SETTINGS len=6, settings: MAX_FRAME_SIZE=16384
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: read SETTINGS len=6, settings: ENABLE_PUSH=0
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: wrote SETTINGS flags=ACK len=0
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: read SETTINGS flags=ACK len=0
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: read HEADERS flags=END_HEADERS stream=1 len=169
2021/12/27 22:25:25 http2: decoded hpack field header field ":method" = "POST"
2021/12/27 22:25:25 http2: decoded hpack field header field ":scheme" = "http"
2021/12/27 22:25:25 http2: decoded hpack field header field ":path" = "/protofiles.UserService/GetUserById"
2021/12/27 22:25:25 http2: decoded hpack field header field ":authority" = "10.0.2.2:8080"
2021/12/27 22:25:25 http2: decoded hpack field header field "content-type" = "application/grpc"
2021/12/27 22:25:25 http2: decoded hpack field header field "te" = "trailers"
2021/12/27 22:25:25 http2: decoded hpack field header field "user-agent" = "dart-grpc/2.0.0"
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: read DATA stream=1 len=69 data="\x00\x00\x00\x00@\n>\b\x05\x12\x00\x1a\x00\"\x00(\x002\f\b\xa4\xa6\xa8\x8e\x06\x10\xa0\xb7\x93\xf1\x01:\x00B\x00J\f\b\xa4\xa6\xa8\x8e\x06\x10\xf0ɒ\xf1\x01R\b\b\x00\x10\x00\x18\x00 \x00X\x00`\x00h\x00p\x00z\x00"
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: wrote WINDOW_UPDATE len=4 (conn) incr=69
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: wrote PING len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: read DATA flags=END_STREAM stream=1 len=0 data=""
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: wrote HEADERS flags=END_STREAM|END_HEADERS stream=1 len=90
2021/12/27 22:25:25 http2: Framer 0xc0002b2000: read PING flags=ACK len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"

这是原型消息和端点:

message User{
    int64 id = 1;
    string username = 2;
    string auth_user_id = 3;
    string email = 4;
    string display_name = 5;
    Gender gender = 6;
}
func (u *UserService) GetUserById(ctx context.Context, in *protofiles.GetUserRequest) (*protofiles.GetUserResponse, error) {
    user, err := u.store.GetByID(in.User.Id)
    if err != nil {
        return &protofiles.GetUserResponse{}, err
    }
    return &protofiles.GetUserResponse{User: models.UserHelper.ToProto(user)}, nil
}

经过几个小时的反复试验,我终于弄清楚了问题所在,就像许多其他错误一样,它被证明是一个愚蠢的错误。 原始文件消息中标签的顺序已更改(在顶部添加了一个新字段,所有其他字段都向下推)。服务器使用新定义,而客户端使用旧定义。当客户端尝试调用端点时,标签不匹配。

我所要做的就是为客户端存根重新生成文件。