当前位置: 首页 > article >正文

gRPC学习之六:gRPC-Gateway集成swagger

  • 还要把swaggerdemo.proto中提到的protoc-gen-swagger/options/annotations.proto文件放在合适的地方,以便使用swaggerdemo.proto的时候能找到此annotations.proto文件,执行以下命令:

cd $GOPATH/src

cp -r ./github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger ./

  • 上述命令中的protoc-gen-swagger文件夹,是在前文的操作中下载好的;

生成gRPC、gRPC-Gateway所需的go源码

  • 生成gRPC、gRPC-Gateway所需的go源码,这样的操作在前面已经做过,这里用swaggerdemo.proto再做一次,先进入目录$GOPATH/src/swaggerdemo

  • 执行以下命令,生成gRPC所需源码:

protoc -I. \

-I$GOPATH/src \

-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

–go_out=plugins=grpc:. \

swaggerdemo.proto

  • 执行以下命令,生成gRPC-Gateway所需源码:

protoc -I. \

-I$GOPATH/src \

-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

–grpc-gateway_out=logtostderr=true:. \

swaggerdemo.proto

生成swagger所需的json文件

  • 还是在目录$GOPATH/src/swaggerdemo,执行以下命令,生成swagger所需json:

protoc -I. \

-I$GOPATH/src \

-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

–swagger_out=logtostderr=true:. \

swaggerdemo.proto

  • 此时的$GOPATH/src/swaggerdemo目录下新增以下三个文件:
  1. swaggerdemo.pb.go:gRPC所需的go文件

  2. swaggerdemo.pb.gw.go:gRPC-Gateway所需的go文件

  3. swaggerdemo.swagger.json:swagger-ui要用的json文件,依据此文件,swagger展现的页面中会有gRPC-Gateway暴露的服务和参数定义,可以在页面上发起请求

生成swagger-ui的go文件

  • 要想在服务中提供swagger的web页面,需要将swagger-ui的源码转为go文件,步骤如下:
  1. 接下来的命令会从Github下载swagger-ui的源码,这个文件本该从swagger官方下载,但是我这里尝试多次后发现,下载得到的zip包很容器出现文件损坏而无法解压缩的情况,于是我将此文件放在了自己的Github上,下面的操作也是从我自己的Github下载的,但实际上此文件和swagger官方的并无区别;

  2. 进入目录$GOPATH/src/swaggerdemo,执行以下命令下载swagger-ui源码,并放入指定位置:

wget https://raw.githubusercontent.com/zq2599/blog_download_files/master/files/swagger-ui.zip -O swagger-ui.zip \

&& unzip swagger-ui.zip \

&& mkdir -p $GOPATH/src/swaggerdemo/third_party/ \

&& mv ./swagger-ui-3.38.0/dist $GOPATH/src/swaggerdemo/third_party/ \

&& mv $GOPATH/src/swaggerdemo/third_party/dist $GOPATH/src/swaggerdemo/third_party/swagger-ui \

&& rm -f ./swagger-ui.zip \

&& rm -rf ./swagger-ui-3.38.0

  1. 执行以下命令新建文件夹,该文件夹用来存放稍后生成的swagger-ui的go源码:

mkdir -p $GOPATH/src/swaggerdemo/pkg/ui/data/swagger

  1. 执行以下命令,将swagger-ui源码转为datafile.go文件:

cd $GOPATH/src/swaggerdemo/

go-bindata --nocompress -pkg swagger -o pkg/ui/data/swagger/datafile.go third_party/swagger-ui/…

  1. 这时候在$GOPATH/src/swaggerdemo/pkg/ui/data/swagger目录下生成了文件datafile.go
  • 所有文件和材料已经准备完成,开始编码;

编写gRPC的服务端代码

  • 按照swaggerdemo.proto的配置新建一个gRPC服务,步骤如下:
  1. 新建文件夹$GOPATH/src/swaggerdemo/server;

  2. 在新建的server文件夹下新增文件server.go,内容如下,只是个普通的gRPC服务而已:

package main

import (

“context”

“log”

“net”

“google.golang.org/grpc”

pb “swaggerdemo”

)

const (

port = “:50051”

)

// 定义结构体,在调用注册api的时候作为入参,

// 该结构体会带上SayHello方法,里面是业务代码

// 这样远程调用时就执行了业务代码了

type server struct {

// pb.go中自动生成的,是个空结构体

pb.UnimplementedGreeterServer

}

// 业务代码在此写,客户端远程调用SayHello时,

// 会执行这里的代码

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {

// 打印请求参数

log.Printf(“Received: %v”, in.GetName())

// 实例化结构体HelloReply,作为返回值

return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil

}

func main() {

// 要监听的协议和端口

lis, err := net.Listen(“tcp”, port)

if err != nil {

log.Fatalf(“failed to listen: %v”, err)

}

// 实例化gRPC server结构体

s := grpc.NewServer()

// 服务注册

pb.RegisterGreeterServer(s, &server{})

log.Println(“开始监听,等待远程调用…”)

if err := s.Serve(lis); err != nil {

log.Fatalf(“failed to serve: %v”, err)

}

}

  • 以上就是gRPC服务的代码,与前几篇文章中的差不多,就不赘述了;

编写gRPC-Gateway服务端的代码

  • 开始编写gRPC-Gateway服务端代码,这是本文的重点所在,除了提供与前文一样的gRPC-Gateway服务,还提供了swagger的json文件服务,以及swagger的ui服务;

  • 新建文件夹$GOPATH/src/swaggerdemo/gateway;

  • 在新建的gateway文件夹下新增文件gateway.go,内容如下,有几处要注意的地方稍后会说明:

package main

import (

“github.com/elazarl/go-bindata-assetfs”

“log”

“net/http”

“path”

“strings”

“github.com/golang/glog”

“github.com/grpc-ecosystem/grpc-gateway/runtime”

“golang.org/x/net/context”

“google.golang.org/grpc”

swagger “swaggerdemo/pkg/ui/data/swagger”

gw “swaggerdemo”

)

func run() error {

ctx := context.Background()

ctx, cancel := context.WithCancel(ctx)

defer cancel()

gwmux, err := newGateway(ctx)

if err != nil {

panic(err)

}

mux := http.NewServeMux()

mux.Handle(“/”, gwmux)

mux.HandleFunc(“/swagger/”, serveSwaggerFile)

serveSwaggerUI(mux)

log.Println(“grpc-gateway listen on localhost:9090”)

return http.ListenAndServe(“:9090”, mux)

}

func newGateway(ctx context.Context) (http.Handler, error) {

opts := []grpc.DialOption{grpc.WithInsecure()}

gwmux := runtime.NewServeMux()

if err := gw.RegisterGreeterHandlerFromEndpoint(ctx, gwmux, “:50051”, opts); err != nil {

return nil, err

}

return gwmux, nil

}

func serveSwaggerFile(w http.ResponseWriter, r *http.Request) {

log.Println(“start serveSwaggerFile”)

if !strings.HasSuffix(r.URL.Path, “swagger.json”) {

log.Printf(“Not Found: %s”, r.URL.Path)

http.NotFound(w, r)

return

}

p := strings.TrimPrefix(r.URL.Path, “/swagger/”)

p = path.Join(“…/”, p)

log.Printf(“Serving swagger-file: %s”, p)

http.ServeFile(w, r, p)

}

func serveSwaggerUI(mux *http.ServeMux) {

fileServer := http.FileServer(&assetfs.AssetFS{

Asset: swagger.Asset,

AssetDir: swagger.AssetDir,

Prefix: “third_party/swagger-ui”,

})

prefix := “/swagger-ui/”

mux.Handle(prefix, http.StripPrefix(prefix, fileServer))

}

func main() {

defer glog.Flush()

if err := run(); err != nil {

glog.Fatal(err)

}


http://www.kler.cn/a/289600.html

相关文章:

  • LeetCode 86.分隔链表
  • 比ChatGPT更酷的AI工具
  • Lucene 和 Elasticsearch 中更好的二进制量化 (BBQ)
  • 机器学习day3-KNN算法、模型调优与选择
  • 10款翻译工具实践体验感受与解析!!!!!
  • 【深圳大学】数据结构A+攻略(计软版)
  • 山东省行政执法证照片要求及图像处理方法
  • 实训day40(8.30)
  • 数据结构-广义表
  • 在uni-app中使用SQLite
  • office套件打开时 提示操作系统当前的配置不能运行此应用程序
  • VS2022使用指定的LLVM版本
  • windows 环境下安装OpenCV For Java
  • 一些可能很有用的矩阵知识
  • 新手c语言讲解及题目分享(十)——数组专项练习
  • 免费GPU平台教程,助力你的AI, pytorch tensorflow 支持cuda
  • Vue3组件通信概览
  • [Raspberry Pi]如何利用docker執行motioneye,並利用Line Notify取得即時通知和照片?
  • 2024车牌识别系统十大品牌发布,车牌智能识别系统品牌哪家好?
  • 【408 数据结构】第1章绪论
  • 开发基础软件安装地址(持续更新中)
  • Spring Boot实战:运用享元模式优化微服务间共享资源
  • 使用VM创建centos7环境
  • 知识点复习3
  • 速盾:什么是高防cdn?高防cdn的特点和好处有哪些?
  • 微信小程序知识点(一)