golang 工程组件:grpc-gateway option自定义http规则

option自定义http规则和http body响应

简介

本篇接上文

golang 工程组件:grpc-gateway 环境安装+默认网关测试

默认网关配置终究是难用,本篇介绍一下proto里采用option自定义http规则以及让网关返回http响应而不是我们定义的grpc响应

option定义http规则和httpbody响应

引入库。可以直接拷贝grpc-gateway源码下google文件夹到项目下

import "google/api/annotations.proto";
import "google/api/httpbody.proto";
import "google/protobuf/empty.proto";

user.proto

syntax = "proto3";
package  echo;
option go_package = "echo/proto";

import "google/api/annotations.proto";
import "google/api/httpbody.proto";
import "google/protobuf/empty.proto";


message User{
  int64 id = 1;
  // 改成下划线形式
  string userName = 2[json_name="user_name"];
  int32 age = 3;
  string phone = 4;
  Addr addr = 5;
}

message Addr {
  string province = 1;
  string city = 2;
  string county = 3;
}

service Echo{
  rpc Get(User) returns (User) {
  	//get请求
    option (google.api.http) = {
      get: "/echo/user/{id}"
    };
  }
  rpc AddOrUpdate(User) returns (User) {
    option (google.api.http) = {
      post: "/echo/user"
      // * 表示接受user所有字段
      body: "*"
      additional_bindings {
        put: "/echo/user"
        body: "*"
      }
      //patch 请求,只更新部分字段
      additional_bindings {
        patch: "/echo/user"
        body: "addr"
      }
    };
  }
  rpc Delete(User) returns (User) {
    option (google.api.http) = {
        delete: "/echo/user/{id}"
     };
  }
  // httpbody响应,前面是grpc定义的消息
  rpc List(google.protobuf.Empty) returns (stream google.api.HttpBody) {
    option (google.api.http) = {
       get: "/echo/user/list"
    };
  }
}

对应grpc实现

server.go

package server

import (
    "context"
    "echo/proto"
    "fmt"
    "github.com/golang/protobuf/jsonpb"
    _ "github.com/golang/protobuf/jsonpb"
    "google.golang.org/genproto/googleapis/api/httpbody"
    _ "google.golang.org/genproto/googleapis/api/httpbody"
    "google.golang.org/protobuf/types/known/emptypb"
    _ "google.golang.org/protobuf/types/known/emptypb"
)

type echoServer struct {
    proto.UnimplementedEchoServer
}

func NewServer() proto.EchoServer {
    return &echoServer{}
}
func (s *echoServer) Get(ctx context.Context, in *proto.User) (*proto.User, error) {
    fmt.Printf("%+v\n", in)
    return in, nil
}
func (s *echoServer) AddOrUpdate(ctx context.Context, in *proto.User) (*proto.User, error) {
    fmt.Printf("%+v\n", in)
    return in, nil
}
func (s *echoServer) Delete(ctx context.Context, in *proto.User) (*proto.User, error) {
    fmt.Printf("%+v\n", in)
    return in, nil
}

func (s *echoServer) List(in *emptypb.Empty, stream proto.Echo_ListServer) error {
    userList := []*proto.User{
        {
            Id:       1,
            UserName: "test1",
            Addr: &proto.Addr{
                Province: "深圳1",
            },
        },
        {
            Id:       2,
            UserName: "test2",
            Addr: &proto.Addr{
                Province: "深圳2",
            },
        },
        {
            Id:       3,
            UserName: "test3",
            Addr: &proto.Addr{
                Province: "深圳3",
            },
        },
    }
    for _, u := range userList {
        //jsonpb库序列化返回的才是下划线形式。 json序列化不读tag里定义
        m := jsonpb.Marshaler{}
        data, _ := m.MarshalToString(u)
        msg := &httpbody.HttpBody{
            ContentType: "application/json",
            Data:        []byte(data),
        }
        stream.Send(msg)
    }
    return nil
}

启动后按对应路由访问即可。 网关和启动源码在上文里

你可能感兴趣的:(1024程序员节,golang,gateway,http,服务器,后端)