Compare commits

..

2 Commits

Author SHA1 Message Date
c207152892 cleanup
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-06 19:04:42 +03:00
Кирилл Горбунов
7a302ce899 #2 - add swaggerset (#8)
Co-authored-by: Gorbunov Kirill Andreevich <kgorbunov@mtsbank.ru>
Reviewed-on: #8
Reviewed-by: Василий Толстов <v.tolstov@unistack.org>
Co-authored-by: Кирилл Горбунов <kirya_gorbunov_2015@mail.ru>
Co-committed-by: Кирилл Горбунов <kirya_gorbunov_2015@mail.ru>
2024-12-06 19:01:07 +03:00
6 changed files with 165 additions and 179 deletions

View File

@@ -7,7 +7,6 @@ import (
"os/signal" "os/signal"
"time" "time"
openapi_v3 "github.com/google/gnostic/openapiv3"
"github.com/google/uuid" "github.com/google/uuid"
grpccli "go.unistack.org/micro-client-grpc/v3" grpccli "go.unistack.org/micro-client-grpc/v3"
httpcli "go.unistack.org/micro-client-http/v3" httpcli "go.unistack.org/micro-client-http/v3"
@@ -31,6 +30,7 @@ import (
"go.unistack.org/servicechecker/pkg/httpconn" "go.unistack.org/servicechecker/pkg/httpconn"
"go.unistack.org/servicechecker/pkg/protoset" "go.unistack.org/servicechecker/pkg/protoset"
"go.unistack.org/servicechecker/pkg/scheduler" "go.unistack.org/servicechecker/pkg/scheduler"
"go.unistack.org/servicechecker/pkg/swaggerset"
) )
var ( var (
@@ -213,8 +213,10 @@ func newHTTPTask(ctx context.Context, l logger.Logger, m meter.Meter, check stri
var treq client.Request var treq client.Request
var opts []client.CallOption var opts []client.CallOption
var labels []string var labels []string
swaggerSet := swaggerset.NewSwaggerSet()
if task.HTTP.OpenAPI != "" { if task.HTTP.OpenAPI != "" {
var svc string
openapiBuf, err := os.ReadFile(task.HTTP.OpenAPI) openapiBuf, err := os.ReadFile(task.HTTP.OpenAPI)
if err != nil { if err != nil {
@@ -222,12 +224,11 @@ func newHTTPTask(ctx context.Context, l logger.Logger, m meter.Meter, check stri
return nil, nil, err return nil, nil, err
} }
doc, err := openapi_v3.ParseDocument(openapiBuf) err = swaggerSet.AddSwaggerset(task.HTTP.Addr, svc, openapiBuf)
if err != nil { if err != nil {
l.Error(ctx, "failed to unmarshal openapi file", err) l.Error(ctx, "failed to add openApi spec", err)
return nil, nil, err return nil, nil, err
} }
_ = doc
errmap := make(map[string]interface{}, 1) errmap := make(map[string]interface{}, 1)
errmap["default"] = &codecpb.Frame{} errmap["default"] = &codecpb.Frame{}
@@ -239,8 +240,17 @@ func newHTTPTask(ctx context.Context, l logger.Logger, m meter.Meter, check stri
// client.WithContentType("application/json"), // client.WithContentType("application/json"),
} }
msg, err := swaggerSet.GetMessage(task.HTTP.Addr, svc, task.HTTP.Method)
if err != nil {
l.Error(ctx, "failed to get message from swagger spec", err)
return nil, nil, err
}
req = &codecpb.Frame{Data: []byte(task.HTTP.Data)} req = &codecpb.Frame{Data: []byte(task.HTTP.Data)}
rsp = &codecpb.Frame{} if task.HTTP.Data == "" {
req = msg.Request
}
rsp = msg.Response
treq = c.NewRequest(task.Name, task.Name, req) treq = c.NewRequest(task.Name, task.Name, req)

12
go.mod
View File

@@ -3,9 +3,7 @@ module go.unistack.org/servicechecker
go 1.23.3 go 1.23.3
require ( require (
github.com/getkin/kin-openapi v0.128.0
github.com/go-co-op/gocron/v2 v2.12.3 github.com/go-co-op/gocron/v2 v2.12.3
github.com/google/gnostic v0.7.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/ompluscator/dynamic-struct v1.4.0 github.com/ompluscator/dynamic-struct v1.4.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
@@ -24,17 +22,13 @@ require (
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/google/gnostic v0.7.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/valyala/fastrand v1.1.0 // indirect github.com/valyala/fastrand v1.1.0 // indirect
github.com/valyala/histogram v1.2.0 // indirect github.com/valyala/histogram v1.2.0 // indirect
go.unistack.org/metrics v0.0.1 // indirect go.unistack.org/metrics v0.0.1 // indirect

20
go.sum
View File

@@ -660,8 +660,6 @@ github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6Ni
github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/getkin/kin-openapi v0.128.0 h1:jqq3D9vC9pPq1dGcOCv7yOp1DaEe7c/T1vzcLbITSp4=
github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-co-op/gocron/v2 v2.12.3 h1:3JkKjkFoAPp/i0YE+sonlF5gi+xnBChwYh75nX16MaE= github.com/go-co-op/gocron/v2 v2.12.3 h1:3JkKjkFoAPp/i0YE+sonlF5gi+xnBChwYh75nX16MaE=
github.com/go-co-op/gocron/v2 v2.12.3/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w= github.com/go-co-op/gocron/v2 v2.12.3/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
@@ -675,14 +673,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -798,12 +790,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
@@ -827,20 +815,14 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/ompluscator/dynamic-struct v1.4.0 h1:I/Si9LZtItSwiTMe7vosEuIu2TKdOvWbE3R/lokpN4Q= github.com/ompluscator/dynamic-struct v1.4.0 h1:I/Si9LZtItSwiTMe7vosEuIu2TKdOvWbE3R/lokpN4Q=
github.com/ompluscator/dynamic-struct v1.4.0/go.mod h1:ADQ1+6Ox1D+ntuNwTHyl1NvpAqY2lBXPSPbcO4CJdeA= github.com/ompluscator/dynamic-struct v1.4.0/go.mod h1:ADQ1+6Ox1D+ntuNwTHyl1NvpAqY2lBXPSPbcO4CJdeA=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
@@ -887,8 +869,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=

View File

@@ -1,75 +1,78 @@
package swaggerset package swaggerset
import ( import (
"context"
"errors" "errors"
"fmt" "net/http"
"sync" "sync"
"github.com/getkin/kin-openapi/openapi3" openapi "go.unistack.org/micro-proto/v3/openapiv3"
) )
var errNotFound = errors.New("file descriptor not found") var errNotFound = errors.New("file descriptor not found")
type SwaggerSet struct { type SwaggerSet struct {
mu sync.Mutex mu sync.Mutex
files map[string]*openapi3.T files map[string]*openapi.Document
} }
func NewSwaggerSet() *SwaggerSet { func NewSwaggerSet() *SwaggerSet {
return &SwaggerSet{ return &SwaggerSet{
mu: sync.Mutex{}, mu: sync.Mutex{},
files: make(map[string]*openapi3.T, 0), files: make(map[string]*openapi.Document, 0),
} }
} }
func (p *SwaggerSet) GetMessage(addr, svc, mth, typereq string) (*messages, error) { func (p *SwaggerSet) GetMessage(addr, svc, mth string) (*Message, error) {
if svc == "" || mth == "" || addr == "" || typereq == "" { if svc == "" || mth == "" || addr == "" {
return nil, errors.New("addr or service name is empty") return nil, errors.New("addr or service name is empty")
} }
messages := newMessages()
p.mu.Lock() p.mu.Lock()
doc := p.files[addr+"|"+svc] doc := p.files[addr+"|"+svc]
p.mu.Unlock() p.mu.Unlock()
pathItem := doc.Paths.Value(mth) var reqParam, reqBody, rsp interface{}
if pathItem.Get != nil { var typeReq string
reqParam, reqBody, rsp := handleOperation("GET", pathItem.Get) for _, path := range doc.Paths.GetPath() {
messages.Msgs = append(messages.Msgs, message{ if path.GetName() == mth {
Type: "GET", if path.GetValue().GetGet() != nil {
RequestParam: reqParam, typeReq = http.MethodGet
RequestBody: reqBody, reqParam, reqBody, rsp = handleOperation(path.GetValue().GetGet(), doc)
Response: rsp,
})
} }
if pathItem.Post != nil { if path.GetValue().GetPost() != nil {
reqParam, reqBody, rsp := handleOperation("POST", pathItem.Post) typeReq = http.MethodPost
messages.Msgs = append(messages.Msgs, message{ reqParam, reqBody, rsp = handleOperation(path.GetValue().GetPost(), doc)
Type: "POST", }
RequestParam: reqParam, if path.GetValue().GetDelete() != nil {
RequestBody: reqBody, typeReq = http.MethodDelete
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetDelete(), doc)
}
if path.GetValue().GetPatch() != nil {
typeReq = http.MethodPatch
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetPatch(), doc)
}
if path.GetValue().GetPut() != nil {
typeReq = http.MethodPut
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetPut(), doc)
}
}
}
msg := &Message{
Type: typeReq,
Request: httpRequest{
Header: reqParam,
Body: reqBody,
},
Response: rsp, Response: rsp,
})
} }
return messages, nil return msg, nil
} }
func (p *SwaggerSet) AddSwaggerset(addr, svc string, data []byte) error { func (p *SwaggerSet) AddSwaggerset(addr, svc string, data []byte) error {
ctx := context.Background() doc, err := openapi.ParseDocument(data)
loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true
doc, err := loader.LoadFromData(data)
if err != nil { if err != nil {
return fmt.Errorf("failed to load data from buf: %w", err) return err
}
if err = doc.Validate(ctx); err != nil {
return fmt.Errorf("failed to validate data from swagger: %w", err)
} }
p.mu.Lock() p.mu.Lock()

View File

@@ -17,24 +17,17 @@ func TestSwaggerSet_1(t *testing.T) {
err = s.AddSwaggerset("localhost:8080", "service", data) err = s.AddSwaggerset("localhost:8080", "service", data)
assert.Nil(t, err) assert.Nil(t, err)
msgs, err := s.GetMessage( msg, err := s.GetMessage(
"localhost:8080", "localhost:8080",
"service", "service",
"/domain-service/v1/push_mail/enabled", "/domain-service/v1/push_mail/enabled",
"POST") "GET")
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, msgs.Msgs) assert.NotNil(t, msg)
for _, msg := range msgs.Msgs { req, err := json.Marshal(msg.Request)
reqParam, err := json.Marshal(msg.RequestParam)
assert.Nil(t, err)
reqBody, err := json.Marshal(msg.RequestBody)
assert.Nil(t, err) assert.Nil(t, err)
rsp, err := json.Marshal(msg.Response) rsp, err := json.Marshal(msg.Response)
assert.Nil(t, err) assert.Nil(t, err)
fmt.Printf("type: %s, reqParam: %s, reqBody: %s, rsp: %s \n", msg.Type, reqParam, reqBody, rsp) fmt.Printf("JSON: type: %s, req: %s, rsp: %s \n", msg.Type, req, rsp)
} fmt.Printf("Struct: type: %s, req: %+v, rsp: %+v \n", msg.Type, msg.Request, msg.Response)
}
func TestSwaggerSet_2(t *testing.T) {
Run4()
} }

View File

@@ -1,107 +1,86 @@
package swaggerset package swaggerset
import ( import (
"encoding/json"
"fmt" "fmt"
"log"
"reflect" "reflect"
"strings" "strings"
"github.com/getkin/kin-openapi/openapi3"
dynamicstruct "github.com/ompluscator/dynamic-struct" dynamicstruct "github.com/ompluscator/dynamic-struct"
openapi "go.unistack.org/micro-proto/v3/openapiv3"
) )
type messages struct { type Message struct {
Msgs []message
}
func newMessages() *messages {
return &messages{
Msgs: make([]message, 0),
}
}
type message struct {
Type string Type string
RequestParam interface{} Request httpRequest
RequestBody interface{}
Response interface{} Response interface{}
} }
func Run4() { type httpRequest struct {
// Загружаем Swagger-документ Header interface{}
loader := openapi3.NewLoader() Body interface{}
doc, err := loader.LoadFromFile("swagger2.yaml")
if err != nil {
log.Fatalf("Ошибка загрузки Swagger-документа: %v", err)
} }
// Пример обработки путей func handleOperation(operation *openapi.Operation, doc *openapi.Document) (reqParam, reqBody, rsp interface{}) {
for path, pathItem := range doc.Paths.Map() {
fmt.Printf("Path: %s\n", path)
// Пример обработки методов
if pathItem.Get != nil {
handleOperation("GET", pathItem.Get)
}
if pathItem.Post != nil {
handleOperation("POST", pathItem.Post)
}
}
}
// Обработка операции (GET или POST)
func handleOperation(method string, operation *openapi3.Operation) (reqParam, reqBody, rsp interface{}) {
fmt.Printf(" Method: %s\n", method)
// Обработка параметров (GET) // Обработка параметров (GET)
if len(operation.Parameters) > 0 { if len(operation.Parameters) > 0 {
paramsStruct := dynamicstruct.NewStruct() paramsStruct := dynamicstruct.NewStruct()
for _, paramRef := range operation.Parameters { for _, paramRef := range operation.Parameters {
param := paramRef.Value var param *openapi.Parameter
param = paramRef.GetParameter()
fieldName := capitalize(param.Name) fieldName := capitalize(param.Name)
goType := getGoType(param.Schema) jsonName := strings.ToLower(param.Name[:1]) + param.Name[1:]
goType := getGoType(doc, param.Schema)
// В зависимости от того, где параметр находится (header, query, path, etc.), добавляем соответствующий тег // В зависимости от того, где параметр находится (header, query, path, etc.), добавляем соответствующий тег
switch param.In { switch param.In {
case "query": case "query":
paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s" query:"%s"`, param.Name, param.Name)) paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s" query:"%s"`, jsonName, jsonName))
case "header": case "header":
paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s" header:"%s"`, param.Name, param.Name)) paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s" header:"%s"`, jsonName, jsonName))
default: default:
paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s"`, param.Name)) paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s"`, jsonName))
} }
} }
requestStruct := paramsStruct.Build().New() // Получили структуру запроса для методов, где есть параметры в header, query, path, etc., добавили теги
fmt.Printf(" Request (Parameters): %+v\n", requestStruct) reqParam = paramsStruct.Build().New()
buf, _ := json.Marshal(requestStruct)
fmt.Printf(" Request (Parameters) JSON: %s\n", buf)
reqParam = requestStruct
} }
// Обработка тела запроса (POST) // Обработка тела запроса (POST)
if operation.RequestBody != nil { if operation.GetRequestBody() != nil {
for _, content := range operation.RequestBody.Value.Content { if operation.GetRequestBody().GetRequestBody() != nil {
bodyFields := buildDynamicStruct(content.Schema) bodyFields := buildDynamicStruct(doc, operation.GetRequestBody().GetRequestBody().GetContent().GetAdditionalProperties()[0].GetValue().GetSchema())
bodyStruct := reflect.StructOf(bodyFields) bodyStruct := reflect.StructOf(bodyFields)
bodyInstance := reflect.New(bodyStruct).Interface() bodyInstance := reflect.New(bodyStruct).Interface()
fmt.Printf(" Request (Body): %+v\n", bodyInstance) // Получили тело запроса
buf, _ := json.Marshal(bodyInstance) reqBody = bodyInstance
fmt.Printf(" Request (Body) JSON: %s\n", buf) }
if operation.GetRequestBody().GetReference() != nil {
schemOrRef := findReference(doc, operation.GetRequestBody().GetReference().GetXRef())
bodyFields := buildDynamicStruct(doc, schemOrRef)
bodyStruct := reflect.StructOf(bodyFields)
bodyInstance := reflect.New(bodyStruct).Interface()
// Получили тело запроса
reqBody = bodyInstance reqBody = bodyInstance
} }
} }
// Обработка ответов // Обработка ответов
for status, response := range operation.Responses.Map() { for _, rspOrRef := range operation.Responses.ResponseOrReference {
fmt.Printf(" Response Code: %s\n", status) if rspOrRef.GetValue().GetResponse() != nil {
for _, content := range response.Value.Content { for _, prop := range rspOrRef.Value.GetResponse().GetContent().GetAdditionalProperties() {
responseFields := buildDynamicStruct(content.Schema) responseFields := buildDynamicStruct(doc, prop.GetValue().GetSchema())
responseStruct := reflect.StructOf(responseFields) responseStruct := reflect.StructOf(responseFields)
responseInstance := reflect.New(responseStruct).Interface() responseInstance := reflect.New(responseStruct).Interface()
fmt.Printf(" Response: %+v\n", responseInstance) // Получили структуру ответа
buf, _ := json.Marshal(responseInstance) rsp = responseInstance
fmt.Printf(" Response JSON: %s\n", buf) }
}
if rspOrRef.GetValue().GetReference() != nil {
schemaOrRef := findReference(doc, rspOrRef.GetValue().GetReference().GetXRef())
responseFields := buildDynamicStruct(doc, schemaOrRef)
responseStruct := reflect.StructOf(responseFields)
responseInstance := reflect.New(responseStruct).Interface()
// Получили структуру ответа
rsp = responseInstance rsp = responseInstance
} }
} }
@@ -110,59 +89,86 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
} }
// Рекурсивное создание структуры из схемы с учетом $ref // Рекурсивное создание структуры из схемы с учетом $ref
func buildDynamicStruct(schema *openapi3.SchemaRef) []reflect.StructField { func buildDynamicStruct(doc *openapi.Document, schemaOrRef *openapi.SchemaOrReference) []reflect.StructField {
var builder []reflect.StructField var sfields []reflect.StructField
fmt.Println("ref: ", schema.Ref) var schema *openapi.Schema
if schemaOrRef.GetSchema() != nil {
if len(schema.Value.Properties) == 0 { schema = schemaOrRef.GetSchema()
return builder
} }
if schemaOrRef.GetReference() != nil {
for name, prop := range schema.Value.Properties { name := strings.Split(schemaOrRef.GetReference().GetXRef(), "#/components/schemas/")[1]
fieldName := capitalize(name) fieldName := capitalize(name)
if prop.Ref != "" || prop.Value.Type.Is("object") { subBuilder := buildDynamicStruct(doc, findReference(doc, schemaOrRef.GetReference().GetXRef()))
subBuilder := buildDynamicStruct(prop)
sfield := reflect.StructField{ sfield := reflect.StructField{
Name: fieldName, Name: fieldName,
Type: reflect.StructOf(subBuilder), Type: reflect.StructOf(subBuilder),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)), Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
} }
sfields = append(sfields, sfield)
}
for _, prop := range schema.GetProperties().GetAdditionalProperties() {
fieldName := capitalize(prop.GetName())
if prop.GetValue().GetReference() != nil {
subBuilder := buildDynamicStruct(doc, prop.GetValue())
builder = append(builder, sfield)
} else {
sfield := reflect.StructField{ sfield := reflect.StructField{
Name: fieldName, Name: fieldName,
Type: reflect.TypeOf(getGoType(prop)), Type: reflect.StructOf(subBuilder),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)), Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, prop.GetName())),
} }
builder = append(builder, sfield) sfields = append(sfields, sfield)
}
if prop.GetValue().GetSchema() != nil {
sfield := reflect.StructField{
Name: fieldName,
Type: reflect.TypeOf(getGoType(doc, prop.GetValue())),
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, prop.GetName())),
}
sfields = append(sfields, sfield)
} }
} }
return builder return sfields
}
func findReference(doc *openapi.Document, ref string) *openapi.SchemaOrReference {
var result *openapi.SchemaOrReference
ref = strings.Split(ref, "#/components/schemas/")[1]
for _, prop := range doc.Components.Schemas.GetAdditionalProperties() {
if prop.Name == ref {
result = prop.Value
}
}
return result
} }
// Преобразование типа OpenAPI в тип Go // Преобразование типа OpenAPI в тип Go
func getGoType(schema *openapi3.SchemaRef) interface{} { func getGoType(doc *openapi.Document, schema *openapi.SchemaOrReference) interface{} {
switch { switch schema.GetSchema().Type {
case schema.Value.Type.Is("string"): case "string":
return "" return ""
case schema.Value.Type.Is("integer"): case "integer":
return 0 return 0
case schema.Value.Type.Is("boolean"): case "boolean":
return false return false
case schema.Value.Type.Is("array"): case "array":
return []interface{}{} return []interface{}{}
case schema.Value.Type.Is("object"): case "object":
return buildDynamicStruct(schema) return buildDynamicStruct(doc, schema)
default: default:
return nil return nil
} }
} }
func capitalize(fieldName string) string { func capitalize(fieldName string) string {
if fieldName == "" {
return fieldName
}
// Заменяем точки на подчеркивания для унификации // Заменяем точки на подчеркивания для унификации
fieldName = strings.ReplaceAll(fieldName, ".", "_") fieldName = strings.ReplaceAll(fieldName, ".", "_")
@@ -175,7 +181,7 @@ func capitalize(fieldName string) string {
// Обрабатываем каждый фрагмент // Обрабатываем каждый фрагмент
for i := 0; i < len(parts); i++ { for i := 0; i < len(parts); i++ {
// Капитализируем первые буквы всех частей, кроме первой // Капитализируем первые буквы всех частей, кроме первой
parts[i] = strings.Title(parts[i]) parts[i] = strings.Title(parts[i]) // cases.Title(language.English).String(parts[i])
} }
// Собираем строку обратно, соединяя части без подчеркиваний // Собираем строку обратно, соединяя части без подчеркиваний