github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
| 名称 | 链接 | 备注 |
|---|---|---|
| 项目主页 | github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git仓库地址(https) | github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |


在gRPC-Gateway集成swagger服务的过程并不简单,咱们将其中的重点提前看一下,做到心里有数:

4. 要将swaggerdemo.swagger.json文件通过web暴露出来,需要工具go-bindata-assetfs;
5. 使用swagger的方式:打开swagger-ui页面后,将swaggerdemo.swagger.json输入给swagger-ui页面,令其解析后,生成对应的在线接口服务;
[golang@centos7 src]$ tree swaggerdemo/
swaggerdemo/
├── gateway
│ └── gateway.go
├── pkg
│ └── ui
│ └── data
│ └── swagger
│ └── datafile.go
├── server
│ └── server.go
├── swaggerdemo.pb.go
├── swaggerdemo.pb.gw.go
├── swaggerdemo.proto
├── swaggerdemo.swagger.json
└── third_party
└── swagger-ui
├── favicon-16x16.png
├── favicon-32x32.png
├── index.html
├── oauth2-redirect.html
├── 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.map
8 directories, 23 files
go get -u github.com/jteeuwen/go-bindata/...
go get -u github.com/elazarl/go-bindata-assetfs/...
go get -u github.com/golang/glog
// 协议类型
syntax = "proto3";
// 包名
package 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;
}
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
info: {
title: "grpc gateway helloworld sample";
version: "1.0";
};
schemes: HTTP;
};
cd $GOPATH/src
cp -r ./github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger ./
protoc -I.
-I$GOPATH/src
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis
--go_out=plugins=grpc:.
swaggerdemo.proto
protoc -I.
-I$GOPATH/src
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis
--grpc-gateway_out=logtostderr=true:.
swaggerdemo.proto
protoc -I.
-I$GOPATH/src
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis
--swagger_out=logtostderr=true:.
swaggerdemo.proto
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
mkdir -p $GOPATH/src/swaggerdemo/pkg/ui/data/swagger
cd $GOPATH/src/swaggerdemo/
go-bindata --nocompress -pkg swagger -o pkg/ui/data/swagger/datafile.go third_party/swagger-ui/...
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)
}
}
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)
}
}


6. 此时的swagger-ui页面并未展示gRPC-Gateway的接口内容,需要将http://192.168.133.204:9090/swagger/swaggerdemo.swagger.json填入下图红框1中,再点击红框2的按钮,即可正常展示,红框3就是gRPC-Gateway对外暴露的服务:

7. 点击下图红框中的Try it out按钮,即可在页面上向后台发起请求:

8. 如下图,修改红框1中的请求参数,再点击红框2中的按钮,即可发起请求:


我是欣宸,期待与您一同畅游Java世界…
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2005/viewspace-2797164/ ,如需转载,请注明出处,否则将追究法律责任。