Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go-Swagger в продуктиве
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Ilya Kaznacheev
May 30, 2020
Programming
520
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go-Swagger в продуктиве
Ilya Kaznacheev
May 30, 2020
More Decks by Ilya Kaznacheev
See All by Ilya Kaznacheev
Road to four nines
dreamworm
0
30
Many Layers of Availability
dreamworm
0
110
Stateful Solutions: A Hands-On Guide to FSM in Golang
dreamworm
0
210
CQRS
dreamworm
0
190
Building a Cloud-Native PaaS
dreamworm
0
170
Distributed System State Management: When Transactions Are Long and SLA Is High
dreamworm
0
160
How To Create Saga-Free Distributed Transactions
dreamworm
0
83
Architectural decisions in building distributed systems
dreamworm
0
46
Распределенные транзакции без саг
dreamworm
0
220
Other Decks in Programming
See All in Programming
仕様駆動開発の消費期限
watany
7
2k
Laravelで学ぶ Webアプリケーションチューニング入門/web_application_tuning_101
hanhan1978
4
1.7k
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
3.4k
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
750
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
440
数百円から始めるRuby電子工作
tarosay
0
130
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
18k
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
650
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
150
Foundation Models frameworkで画像分析
ryodeveloper
1
510
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
470
自動化したのに回らないテスト運用の壁ーAI時代の品質責任と生産性
mfunaki
0
120
Featured
See All Featured
Everyday Curiosity
cassininazir
0
270
We Have a Design System, Now What?
morganepeng
55
8.2k
A better future with KSS
kneath
240
18k
Leo the Paperboy
mayatellez
8
2.1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Rails Girls Zürich Keynote
gr2m
96
14k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6k
30 Presentation Tips
portentint
PRO
1
360
It's Worth the Effort
3n
188
29k
Transcript
Go-Swagger в продуктиве взлеты и падения
Илья Казначеев Remote Backend SWE Основатель Golang Voronezh Ведущий подкаста
Z-Namespace Организатор конференций и митапов Любитель кофе
Golang Voronezh - ~30 активных участников - митапы - мероприятия
для новичков - открыто и дружелюбно t.me/golang_vrn meetup.com/Golang-Voronezh
что такое swagger?
None
SOAP JSON-PRC GraphQL gRPC OData REST
Representational state transfer (REST) is a software architectural style that
defines a set of constraints to be used for creating Web services Wikipedia
None
swagger: "2.0" info: title: Pet API version: "1.0.0" basePath: /api
schemes: - http paths: /pets: get: summary: List all pets parameters: - name: limit in: query description: "How many items to return at one time" required: true type: integer responses: 200: description: an paged array of pets 400: description: unexpected error
None
None
почему мы используем swagger?
команда синхронизирует изменения в API...
None
библиотеки go-swagger/go-swagger ✭ 5.2 K swaggo/swag ✭ 2.7 K deepmap/oapi-codegen
✭ 440 … grpc-ecosystem/grpc-gateway ✭ 8.5 K
go-swagger
генерация кода swagger generate server -t internal/api --exclude-main
структура сгенерированных файлов internal/api ├ models │ └ ... └
restapi ├ operations │ └ ... ├ configure_<your_service_name>.go ├ doc.go ├ embedded_spec.go └ server.go
как мы генерируем код rm -rf internal/api && mkdir -p
internal/api swagger generate server -t internal/api --exclude-main go mod tidy
? вроде все просто
НЕТ
есть некоторые проблемы - go-swagger - это фреймворк, а не
библиотека - куча сгенерированных типов на каждый чих - несовместим с популярными http библиотеками
давайте фиксить!
net/http хендлеры type CustomResponder func(http.ResponseWriter, runtime.Producer) func (c CustomResponder) WriteResponse(w
http.ResponseWriter, p runtime.Producer) { c(w, p) } func MetricsHandler(p instruments.GetMetricsParams) middleware.Responder { return CustomResponder(func(w http.ResponseWriter, _ runtime.Producer) { promhttp.Handler().ServeHTTP(w, p.HTTPRequest) }) }
простые middleware api := operations.NewSwaggerPetstoreAPI(swaggerSpec) api.InstrumentsGetMetricsHandler = instruments.GetMetricsHandlerFunc(MetricsHandler) api.AddMiddlewareFor("GET", "/metrics",
SomeMiddleware) srv := restapi.NewServer(api) srv.Serve()
middleware с кастомным хендлером h := api.Serve(nil) r := chi.NewRouter()
r.Use( middleware.Recoverer, ) r.With(AuthMiddleware).Group(func(r chi.Router) { r.Handle("/user/*", h) }) r.Mount("/", h) srv.ConfigureAPI() srv.SetHandler(r) srv.Serve()
настройки вне configure_<your_service_name>.go api.Logger = log.Printf api.HTMLProducer = runtime.TextProducer() srv
:= restapi.NewServer(api) srv.EnabledListeners = []string{"http"} srv.Port = conf.HTTPPort srv.Host = conf.HTTPAddr
кастомные имена методов /store/order/{orderId}/items: get: tags: - store summary: Find
purchase order items parameters: - name: orderId in: path required: true type: integer func GetOrderItems( param store.GetStoreOrderOrderIDItemsParams, ) middleware.Responder { items, err := getOrderItems(param.OrderID) if err != nil { return store.NewGetStoreOrderOrderIDItemsNotFound() } res := &models.OrderItems{} // // fill resopnse // return store.NewGetStoreOrderOrderIDItemsOK(). WithPayload(res) }
кастомные имена методов /store/order/{orderId}/items: get: tags: - store summary: Find
purchase order items operationId: getOrderItems parameters: - name: orderId in: path required: true type: integer func GetOrderItems( param store.GetOrderItemsParams, ) middleware.Responder { items, err := getOrderItems(param.OrderID) if err != nil { return store.NewGetOrderItemsNotFound() } res := &models.OrderItems{} // // fill resopnse // return store.NewGetOrderItemsOK(). WithPayload(res) }
встроенная валидация OrderItems: type: object properties: message: type: string maximum:
3 # swg/internal/api/models internal/api/models/order_items.go:45:55: cannot convert m.Message (type string) to type float64
шпаргалка по валидации numbers and integers - multipleOf - maximum
- minimum - exclusiveMaximum - exclusiveMinimum strings - maxLength - minLength - pattern arrays - maxItems - minItems - uniqueItems - maxContains - minContains objects - maxProperties - minProperties - required - dependentRequired any type - type - enum - const
расширения (костыли) x-omitempty x-nullable x-isnullable x-order x-go-custom-tag x-schemes x-go-name x-go-type
x-go-json-string x-go-enum-ci
юнит-тесты func GetOrderByID(param store.GetOrderByIDParams) middleware.Responder { order := models.Order{ ID:
123, PetID: 456, Quantity: 20, Status: "approved", } if param.OrderID != order.ID { return store.NewGetOrderByIDNotFound().WithPayload(&models.ErrorMessage{ Code: http.StatusNotFound, Message: http.StatusText(http.StatusNotFound), }) } return store.NewGetOrderByIDOK().WithPayload(&order) }
юнит-тесты tests := []struct { name string req store.GetOrderByIDParams code
int want string }{ { name: "good test", req: store.GetOrderByIDParams{OrderID: 123}, code: 200, want: `{"id":123,"petId":456,"quantity":20,"status":"approved"}`, }, { name: "bad test", req: store.GetOrderByIDParams{OrderID: 456}, code: 404, want: `{"message":"Not Found", "code":404}`, }, }
юнит-тесты for _, tt := range tests { t.Run(tt.name, func(t
*testing.T) { rr := httptest.NewRecorder() GetOrderByID(tt.req).WriteResponse(rr, runtime.JSONProducer()) assert.JSONEq(t, tt.want, rr.Body.String(), "wrong response body") assert.Equal(t, tt.code, rr.Code, "wrong response code") }) }
None
полезные ссылки json-schema.org/specification.html swagger.io/docs/specification/2-0 goswagger.io bit.ly/go-swagger-in-production
бонус A pluggable go-swagger (in development) github.com/ilyakaznacheev/go-plugger
бонус 2 Insomnia Designer insomnia.rest/products/designer
None
ilyakaznacheev