【问题标题】:I get gRPC Invalid UTF-8 when I make a request to gRPC endpoint from Flutter app当我从 Flutter 应用程序向 gRPC 端点发出请求时,我得到 gRPC Invalid UTF-8
【发布时间】:2021-12-26 20:56:55
【问题描述】:

我正在尝试将 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\x1a$1bcc4186-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
}

【问题讨论】:

  • 消息中的某个字符串字段是否可能包含无效的 UTF-8?您是否能够证明使用 Bloom 发送与使用 Flutter 完全相同的消息(我认为 Bloom 使用 NodeJS 运行时而不是 Dart,所以它主要表明另一个 gRPC 客户端可以无错误地提交相同的消息)?是否有可能您正在使用 Dart|Flutter gRPC 的不同发行版|版本?服务器是用什么语言编写的? (它可能有助于在记录收到的消息以帮助诊断方面提供指导)。
  • 是的,我在 Bloom 中发送相同的消息,我得到所有有效的 UTF-8。正如我在帖子中提到的,我在服务器函数中添加了一个“prinln”行,以便我可以确保请求到达该函数,但没有打印出任何内容,这意味着该方法甚至没有被调用。
  • 服务器是用 Go 编写的。我使用的 Flutter & Dart 版本与我在其他设备上一切正常时使用的版本相同。我无法弄清楚这里到底是什么问题。
  • 如果服务器无法解组传入的请求,您的服务器方法将不会被调用。您可以将调试语句添加到您的 Golang 服务器:GODEBUG=http2debug=2 go run ... 以获取传入请求的详细日志记录
  • 在您的问题中包含原型和示例消息会对您有所帮助。

标签: flutter grpc grpc-dart


【解决方案1】:

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

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

【讨论】:

  • 很高兴看到您解决了您的问题。 IIUC 有一个字段重新编号更改导致中断。如您所见,不鼓励重新编号。见Updating a message type
  • 没错。实际上我正在和一个朋友一起做同一个项目。他更改了编号,我没有重新生成新的客户端存根,导致不匹配。
猜你喜欢
  • 2021-10-19
  • 1970-01-01
  • 2019-09-28
  • 2020-08-17
  • 2021-12-04
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多