Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Go-Swagger in production
Search
Ilya Kaznacheev
June 25, 2020
Programming
580
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go-Swagger in production
Ilya Kaznacheev
June 25, 2020
More Decks by Ilya Kaznacheev
See All by Ilya Kaznacheev
Road to four nines
dreamworm
0
45
Many Layers of Availability
dreamworm
0
120
Stateful Solutions: A Hands-On Guide to FSM in Golang
dreamworm
0
220
CQRS
dreamworm
0
200
Building a Cloud-Native PaaS
dreamworm
0
180
Distributed System State Management: When Transactions Are Long and SLA Is High
dreamworm
0
170
How To Create Saga-Free Distributed Transactions
dreamworm
0
94
Architectural decisions in building distributed systems
dreamworm
0
50
Распределенные транзакции без саг
dreamworm
0
220
Other Decks in Programming
See All in Programming
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
550
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.1k
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
4.3k
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.7k
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
180
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
450
スマート反転とウェブアクセシビリティ
camiha
0
210
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
0
1.1k
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
140
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
Are APIs Still Relevant in the AI Era?
soyuka
0
150
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
310
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
100
6.3k
KATA
mclloyd
PRO
35
15k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
202
76k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
ラッコキーワード サービス紹介資料
rakko
1
4.9M
New Earth Scene 8
popppiees
3
2.6k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.8k
Technical Leadership for Architectural Decision Making
baasie
3
570
AI: The stuff that nobody shows you
jnunemaker
PRO
9
1k
Transcript
Go-Swagger in production wins and pitfalls
Ilya Kaznacheev Remote Backend SWE Founder of Golang Voronezh Host
of Z-Namespace podcast Organizer of conference and meetups Coffee geek
what swagger is?
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
why do we use swagger?
my team trying to sync API changes...
None
go-swagger
code generation swagger generate server -t internal/api --exclude-main
generated code structure internal/api ├ models │ └ ... └
restapi ├ operations │ └ ... ├ configure_<your_service_name>.go ├ doc.go ├ embedded_spec.go └ server.go
our code generation rm -rf internal/api && mkdir -p internal/api
swagger generate server -t internal/api --exclude-main go mod tidy
? and we're all set
NO
there are some problems - go-swagger is a framework, not
a library - plenty of generated types for everything - incompatible with popular http-libraries
let’s fix ’em all!
serving net/http handlers 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) }) }
simple middleware api := operations.NewSwaggerPetstoreAPI(swaggerSpec) api.InstrumentsGetMetricsHandler = instruments.GetMetricsHandlerFunc(MetricsHandler) api.AddMiddlewareFor("GET", "/metrics",
SomeMiddleware) srv := restapi.NewServer(api) srv.Serve()
middleware with custom handler 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()
setup outside of 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
custom method names /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) }
custom method names /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) }
validity checks 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
validity check cheat sheet 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
extensions (tricks) 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
Shortcuts Error: type: object required: - code - message properties:
code: type: integer message: type: string type APIError struct { code int Payload *models.Error `json:"body,omitempty"` } func (e *APIError) WriteResponse( rw http.ResponseWriter, producer runtime.Producer) { rw.WriteHeader(e.code) producer.Produce(rw, e.Payload) } func RespondError(code int, err error) *APIError { return &APIError{ code: code, Payload: &models.Error{code, err.Error()}, } }
unit tests 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) }
unit tests 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}`, }, }
unit tests 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
helpful links json-schema.org/specification.html swagger.io/docs/specification/2-0 goswagger.io bit.ly/go-swagger-in-production
ilyakaznacheev