gRPC之gateway集成swagger
1、gateway集成swagger
1、为了简化实战过程,gRPC-Gateway
暴露的服务并未使用https
,而是http
,但是swagger-ui
提供的调用服
务却是https
的,因此要在proto
文件中指定swagger
以http
调用服务,指定的时候会用到文件
protoc-gen-swagger/options/annotations.proto
,因此需要找到这个文件对应的包,放在合适的位置。
2、swaggerdemo.swagger.json
:这是swagger-ui
要用的json
文件,依据此文件,swagger
才能正确的展现
出gRPC-Gateway
暴露的服务和参数定义,可以在页面上发起请求,此文件由插件protoc-gen-swagger
生成。
3、在gRPC-Gateway
的代码中集成swagger-ui
的代码:swagger-ui
的代码由多个png、html、js
文件组成,
需要用工具go-bindata
转换成go
源码并放入合适的位置,流程如下图:
4、要将swaggerdemo.swagger.json
文件通过web
暴露出来,需要工具go-bindata-assetfs
。
5、使用swagger
的方式:打开swagger-ui
页面后,将swaggerdemo.swagger.json
输入给swagger-ui
页面,
令其解析后,生成对应的在线接口服务。
1.1 安装必要的go包
1、安装protoc-gen-swagger
$ go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
$ go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
2、go-bindata
用来将swagger-ui
的源码转为GO代码:
$ go install github.com/jteeuwen/go-bindata/...
3、go-bindata-assetfs
在应用启动后,对外提供文件服务,这样可以通过web
访问swagger
的json
文件:
$ go install github.com/elazarl/go-bindata-assetfs/...
4、glog
是常用的日志工具:
$ go get -u github.com/golang/glog
1.2 编写proto文件
新建swaggerdemo.proto
:
// 协议类型
syntax = "proto3";// 包名
package swaggerdemo;option go_package="./protoc;swaggerdemo";import "google/api/annotations.proto";
import "protoc-gen-swagger/options/annotations.proto";// 定义swagger内容
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {info: {title: "grpc gateway helloworld sample";version: "1.0";};schemes: HTTP;
};// 定义的服务名
service Greeter {// 具体的远程服务方法rpc SayHello (HelloRequest) returns (HelloReply) {option (google.api.http) = {post: "/helloworld"body: "*"};}
}// SayHello方法的入参,只有一个字符串字段
message HelloRequest {string name = 1;
}// SayHello方法的返回值,只有一个字符串字段
message HelloReply {string message = 1;
}
protoc-gen-swagger/options/annotations.proto
来自于:
github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
生成swaggerdemo.pb.go
,gRPC所需的go文件:
$ protoc --go_out=plugins=grpc:. protoc/swaggerdemo.proto
生成swaggerdemo.pb.gw.go
,gRPC-Gateway所需的go文件:
$ protoc --grpc-gateway_out=logtostderr=true:. protoc/swaggerdemo.proto
生成swaggerdemo.swagger.json
,swagger-ui
要用的json
文件,依据此文件,swagger
展现的页面中会有
gRPC-Gateway
暴露的服务和参数定义,可以在页面上发起请求:
$ protoc --swagger_out=logtostderr=true:. protoc/swaggerdemo.proto
1.3 生成swagger-ui的go文件
从 https://github.com/swagger-api/swagger-ui
下载包,解压把dist
目录下的所有文件拷贝我们项目的
/swagger/swagger-ui/
目录下。
运行指令把Swagger UI
转成datafile.go
代码:
$ go-bindata --nocompress -pkg swagger -o swagger/datafile.go swagger/swagger-ui/...
1.4 编写gRPC的服务端代码
新建文件server.go
,内容如下:
package mainimport ("context""google.golang.org/grpc""log""net"pb "swaggerproject/protoc"
)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)}
}
1.5 编写gRPC-Gateway服务端的代码
新建文件gateway.go
,内容如下:
package mainimport ("github.com/golang/glog""github.com/grpc-ecosystem/grpc-gateway/runtime""golang.org/x/net/context""google.golang.org/grpc""log""net/http""path""strings"gw "swaggerproject/protoc""swaggerproject/swagger"assetfs "github.com/elazarl/go-bindata-assetfs"
)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("./protoc/", 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: "swagger/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)}
}
对于这个gateway.go
文件,有以下几处需要重点注意:
1、外部的RESTful
请求转发到server.go
的功能,被封装到newGateway
方法中;
2、请求URL中如果含有/swagger
,就交给serveSwaggerFile
方法处理,这里面的逻辑是将文件
swaggerdemo.swagger.json
返回给请求方;
3、重点关注serveSwaggerUI
方法,经过该方法的处理后,如果请求URL中含有/swagger-ui
,就会交给前面
生成的datafile.go
处理,也就是打开了swagger-ui的页面;
至此,开发工作已经完成,可以开始验证了。
1.6 测试
[root@zsx swagger_demo]# go run server.go
2023/02/12 19:00:16 开始监听,等待远程调用...[root@zsx swagger_demo]# go run gateway.go
2023/02/12 19:00:28 grpc-gateway listen on localhost:9090
访问 http://127.0.0.1:9090/swagger-ui/
输入 http://127.0.0.1:9090/swagger/swaggerdemo.swagger.json
输入请求数据:
发送请求:
至此,gateway集成swagger完成。
# 项目结构
$ tree swagger_demo/
swagger_demo/
├── gateway.go
├── go.mod
├── google
│ └── api
│ ├── annotations.proto
│ └── http.proto
├── go.sum
├── protoc
│ ├── swaggerdemo.pb.go
│ ├── swaggerdemo.pb.gw.go
│ ├── swaggerdemo.proto
│ └── swaggerdemo.swagger.json
├── protoc-gen-swagger
│ └── options
│ ├── annotations.proto
│ └── openapiv2.proto
├── server.go
└── swagger├── datafile.go└── swagger-ui├── favicon-16x16.png├── favicon-32x32.png├── index.css├── index.html├── oauth2-redirect.html├── swagger-initializer.js├── swagger-ui-bundle.js├── swagger-ui-bundle.js.map├── swagger-ui.css├── swagger-ui.css.map├── swagger-ui-es-bundle-core.js├── swagger-ui-es-bundle-core.js.map├── swagger-ui-es-bundle.js├── swagger-ui-es-bundle.js.map├── swagger-ui.js├── swagger-ui.js.map├── swagger-ui-standalone-preset.js└── swagger-ui-standalone-preset.js.map7 directories, 31 files
相关文章:

gRPC之gateway集成swagger
1、gateway集成swagger 1、为了简化实战过程,gRPC-Gateway暴露的服务并未使用https,而是http,但是swagger-ui提供的调用服 务却是https的,因此要在proto文件中指定swagger以http调用服务,指定的时候会用到文件 prot…...

Pytorch从零开始实战07
Pytorch从零开始实战——咖啡豆识别 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——咖啡豆识别环境准备数据集模型选择训练模型可视化模型预测其他问题总结 环境准备 本文基于Jupyter notebook,使用Python3.8,Pytor…...
大数据知识扫盲
MapReudece作业启动和运行机制 MapReduce是一种分布式计算框架,最初由Google开发,用于处理大规模数据集的批处理任务。其核心思想是将数据划分为小的块,然后并行处理这些块,最后将结果合并。以下是MapReduce作业的启动和运行机制…...
使用Ubuntu虚拟机离线部署RKE2高可用集群
环境说明 宿主机和虚拟机的OS与内核相同,如下 $ cat /etc/issue Ubuntu 22.04.3 LTS \n \l$ uname -sr Linux 6.2.0-34-generic虚拟化软件版本 $ kvm --version QEMU emulator version 6.2.0 (Debian 1:6.2dfsg-2ubuntu6.14) Copyright (c) 2003-2021 Fabrice Be…...

记一次任意文件下载到Getshell
任意文件下载(Arbitrary File Download)是一种常见的 Web 攻击技术,用于窃取服务器上任意文件的内容。攻击者利用应用程序中的漏洞,通过构造恶意请求,使应用程序将任意文件(如配置文件、敏感数据等…...

java异常处理
异常处理分为三类: 检查性异常 用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。 运行时异常 运行时异常是可能被程序员避免的异常…...

递归为什么这么难?一篇文章带你了解递归
递归为什么这么难?一篇文章带你了解递归 美国计算机科学家——彼得多伊奇(L Peter Deutsch)在《程序员修炼之道》(The Pragmatic Programmer)一书中提到“To Iterate is Human, to Recurse, Divine”——我理解的这句话为:人理解迭代,神理解…...

X86(32位)汇编指令与机器码转换原理
X86(32位)汇编指令与机器码转换原理 1 32位寻址形式下的ModR/M字节2 汇编指令转机器码2.1 mov ecx,[eaxebx*2]2.1.1 查Opcode和ModR/M2.1.2 查SIB 2.2 mov ecx,[eaxebx*210h]2.3 mov ecx,[eaxebx*200000100h] 本文属于《 X86指令基础系列教程》之一&…...

ES 全字段模糊检索时分词方式对检索结果的影响
文章目录 背景创建索引指定 _all 分词为空格创建索引插入索引数据全字段的模糊检索 创建索引指定 _all 分词为 keyword索引创建插入数据模糊检索 创建索引不配置 _all不同分词的结果启示录 背景 2018年参与使用 ES 和 Kafka 项目的开发,当时主要是做前端开发&#…...

基于Python Django 的微博舆论、微博情感分析可视化系统(V2.0)
文章目录 1 简介2 意义3 技术栈Django 4 效果图微博首页情感分析关键词分析热门评论舆情预测 5 推荐阅读 1 简介 基于Python的微博舆论分析,微博情感分析可视化系统,项目后端分爬虫模块、数据分析模块、数据存储模块、业务逻辑模块组成。 Python基于微博…...

python读取Excel到mysql
常见问题: 1.数据库密码有特殊字符 使用urllib.parse.quote_plus 编译密码 mysql_engine create_engine((f"mysqlpymysql://root:%s10.0.0.2:3306/mydb")%urllib.parse.quote_plus("passaaaa")) 2.设置字段类型 设置特定类型,和指…...
C++八股文面经
1.介绍一下你对面向对象的理解, 面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它将数据和操作数据的方法组合成一个对象,以此来描述现实世界中的事物和概念。在面向对象编程中&#…...
【Linux】静态库和共享库一分钟快速上手
Linux 前言对比创建静态库动态库 前言 程序库,对于程序原来说是非常重要的。但不少人对其不太了解,接下来一起学习其中的奥秘吧! 简单来说,程序库可以分为静态库和共享库。它们包含了数据和执行代码的文件。其不能单独执行&#…...

C++继承总结(下)——菱形继承
一.什么是菱形继承 菱形继承是多继承的一种特殊情况,一个类有多个父类,这些父类又有相同的父类或者祖先类,那么该类就会有多份重复的成员,从而造成调用二义性和数据冗余。 class Person {public:Person(){cout << "P…...
CCF CCSP2023参赛记 + 算法题题解
大家好啊,时隔多年,作为大四老年人,再次来到这个地方记录算法竞赛相关,可能也是最后一次参加这种算法赛事了,我觉得还是很有纪念意义的。虽然我高中搞OI被强基背刺,以至于到了大学有点躲着竞赛,…...

buuctf_练[GYCTF2020]FlaskApp
[GYCTF2020]FlaskApp 文章目录 [GYCTF2020]FlaskApp常用绕过方法掌握知识解题思路解题一 -- 计算pin码解题二 -- 拼接绕过 执行命令 关键paylaod 常用绕过方法 ssti详解与例题以及绕过payload大全_ssti绕过空格_HoAd’s blog的博客-CSDN博客 CTF 对SSTI的一些总结 - FreeBuf网…...

针对element-plus,跳转jump(快速翻页)
待补充 const goToPage () > {const inputElement document.querySelector(.el-pagination .el-input__inner);console.log(inputElement, inputElement); } 打印之后可以看到分页跳转的数字输入框,是有进行处理的,max"102",是我自己的…...

【软件安装】Windows系统中使用miniserve搭建一个文件服务器
这篇文章,主要介绍如何在Windows系统中使用miniserve搭建一个文件服务器。 目录 一、搭建文件服务器 1.1、下载miniserve 1.2、启动miniserve服务 1.3、指定根目录 1.4、开启访问日志 1.5、指定启动端口 1.6、设置用户认证 1.7、设置界面主题 (…...
iOS .a类型静态库使用终端进行拆解和合并生成
项目中会用到许多第三方的.a类型的静态库,有时候会有一些静态库回包含相同文件而产生冲突,我们就需要对这个库进行去重的一个操作。一般有哪些文件冲突了,xcode报错都会有详细的提示。我们可以将这两个库合并,也可以其中一方中的文…...

react-组件间的通讯
一、父传子 父组件在使用子组件时,提供要传递的数据子组件通过props接收数据 class Parent extends React.Component {render() {return (<div><div>我是父组件</div><Child name"张" age{16} /></div>)} }const Child …...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...