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
}

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

相关推荐
万少5 小时前
DeepSeek 昨晚刚开源了 Harness:附万少的2 万字保姆级教程
前端·后端·架构
布局呆星8 小时前
云服务器上部署单项目/多项目
运维·服务器
盐焗鹌鹑蛋9 小时前
【Linux】缓冲区
linux·运维·服务器
大鸡腿同学9 小时前
身弱体质|你的 FM 该关了📻
后端
Csvn10 小时前
📊 SQL 入门 Day 18:索引原理
后端·sql
Csvn10 小时前
🐍 Day3 : Python 容器精讲 — list、dict、set、tuple 底层实现与高级操作
后端·python
用户9385156350710 小时前
ESLint 代码规范完全指南——从 AST 原理到 flat config 逐行解析
javascript·后端·代码规范
用户9385156350710 小时前
深入理解 Next.js:从 SPA 的 SEO 问题到约定式路由与 SSR 原理
前端·后端·全栈
学代码的CJY11 小时前
Linux 库制作与原理:静态库、动态库、ELF 与动态链接完全指南
linux·运维·服务器
码事漫谈12 小时前
Deepseek涨价了,前后对比,竟然差这么多
后端