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

protobuf 复制代码
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

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
}

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

相关推荐
legend_jz4 分钟前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
黑牛先生6 分钟前
【Linux】进程-PCB
linux·运维·服务器
Karoku06612 分钟前
【企业级分布式系统】ELK优化
运维·服务器·数据库·elk·elasticsearch
新知图书36 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放1 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js
Ares-Wang1 小时前
Asp.net Core Hosted Service(托管服务) Timer (定时任务)
后端·asp.net
安迁岚1 小时前
【SQL Server】华中农业大学空间数据库实验报告 实验三 数据操作
运维·服务器·数据库·sql·mysql
vmlogin虚拟多登浏览器2 小时前
虚拟浏览器可以应对哪些浏览器安全威胁?
服务器·网络·安全·跨境电商·防关联
Rverdoser2 小时前
RabbitMQ的基本概念和入门
开发语言·后端·ruby
追风赶月、3 小时前
【Linux】线程概念与线程控制
linux·运维·服务器