使用 GRPC-Gateway 进行 HTTP 请求时,流式响应的返回值总是 nil,该如何解决?

使用 grpc-gateway 进行 http 请求时,流式响应的返回值总是 nil,该如何解决?

关于 http 请求 grpc-gateway stream 流式响应时无法解码返回值

问题:

使用 grpc-gateway 进行 http 请求时的流式响应,使用 runtime.jsonpb.decode 时,得到的返回值都是 nil

解决:

根据推测,该问题可能有以下几个原因造成:

  • grpc-gateway 版本过低:请升级至 grpc-ecosystem/grpc-gateway/v2 v2.4.0。
  • 返回结果中存在多余字段:grpc-gateway 返回的结果中包含了一个额外的 result 字段。请在 proto 文件中添加以下代码:
// 新增
message httpresp {
 resp result = 1;
}
  • 解码时未使用正确类型:在解码时,请使用 *pb.httpresp 而不是 *pb.resp。

单元测试:

更新代码如下:

package main

import (
    "bytes"
    "net/http"
    "test/pb"
    "testing"

    "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    "google.golang.org/grpc"
)

func testhttprespstream(t *testing.t) {
    url := "http://127.0.0.1:8080/query-stream-resp"
    reqdata := &pb.req{id: 1, name: "111"}

    var buffer bytes.buffer
    encoder := (&runtime.jsonpb{}).newencoder(&buffer)

    if err := encoder.encode(reqdata); err != nil {
        t.fatal(err)
    }

    ctx, cancel := context.withcancel(context.background())
    defer cancel()
    req, err := http.newrequestwithcontext(ctx, http.methodpost, url, &buffer)
    if err != nil {
        t.fatal(err)
    }

    resp, err := http.defaultclient.do(req)
    if err != nil {
        t.fatal(err)
    }
    defer resp.body.close()

    jsonb := new(runtime.jsonpb)
    dencoder := jsonb.newdecoder(resp.body)

    for {
        var result *pb.httpresp // 注意 不要使用 *pb.resp
        err := dencoder.decode(&result) // &result  
        if err == nil {
            t.logf("resp: %+v", result)
        } else {
            t.logf("%+v", err)
            break
        }
    }
}

更新 proto 文件如下:

syntax = "proto3";

package pb;

option go_package = "/pb;pb";

import "google/api/annotations.proto";

message Req {
    int32 id = 1;
    string name = 2;
}

message Resp {
    int32 code = 1;
    string msg = 2;
}

// 新增
message HttpResp {
 Resp result = 1;
}

service TestService {
    rpc QueryStreamResp(Req) returns (stream HttpResp){
        option (google.api.http) = {
            post: "/query-stream-resp"
            body: "*"
        };
    };
    rpc QueryStreamReq(stream Req) returns (Resp){
        option (google.api.http) = {
            post: "/query-stream-req"
            body: "*"
        };
    };
    
    rpc Query(stream Req) returns (stream Resp){
        option (google.api.http) = {
            post: "/query"
            body: "*"
        };
    };
}

更新后,单元测试将能够正确解码流式响应。

以上就是使用 GRPC-Gateway 进行 HTTP 请求时,流式响应的返回值总是 nil,该如何解决?的详细内容,更多请关注其它相关文章!