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
ucon-ajn33
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Masahiro Wakame
June 08, 2016
Technology
1.6k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ucon-ajn33
いかにCloudEndpointsをやめSwaggerを愛するようになったか ajn #33
http://gcpja.connpass.com/event/30761/
Masahiro Wakame
June 08, 2016
More Decks by Masahiro Wakame
See All by Masahiro Wakame
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
790
DatastoreからSpannerに 移行したいぞ途中編 / migrate Datastore to Spanner in progress
vvakame
0
1.3k
Google Cloud Next 2019 わくわく報告会 / Google Cloud Next 2019 WakuWaku Report
vvakame
1
460
メルカリ社員100人に聞いたGoLandの使い方 / JetBrains Night Tokyo 2018
vvakame
27
13k
OSS入門 世界に参加する最初のひと押し / OSS first step
vvakame
7
790
GCP Compute 概要と選定 / DevFest Tokyo 2018
vvakame
12
1.7k
GoでGraphQLサーバを立てるぞ! / Building GraphQL server by go
vvakame
15
4.9k
『Re:VIEW+CSS組版やっていき』を やった話とWebエンジニアが期待する未来 / CSS Publishinng for Web Developers
vvakame
3
9.2k
go.mercari.io/datastore はいいぞ! / go.mercari.io/datastore is pretty good!
vvakame
4
1.2k
Other Decks in Technology
See All in Technology
Let's Change Our World—Again
snoozer05
PRO
6
670
QAエンジニアがSoutherを使ってみたの〜10分でわかるSouther〜
mhlyc
0
120
Draft AIエージェントの トークン消費を最小化する 8つの原則
kinopeee
5
1.7k
演劇と私とスクラム
chinmo
0
140
Codex を使った障害対応机上演習の実際
orgachem
PRO
0
360
導入から定着へ ~コーディングエージェントを日常業務に組み込む実践知~
yukisakai1225
0
230
AIコーディングを実践してきた1年を振り返る / Looking Back on a Year of Practicing AI Coding
takedatakashi
1
110
CSS2026:OWS研究会・招待講演「世界観を、実装する」
atsush1_sada
2
310
正解のない研修に放り出されて / Being thrown into a training program with no right answers
ohnoeight
1
140
「私が一番顧客に詳しい」を捨てる~ 全員が一次情報に精通する開発チームをつくり、PMが次のボトルネックへ染み出すまで
kaminashi
3
2.4k
dbt Semantic Layerで進めるenechainのデータ民主化
akizhou
1
260
AWS Continuum for Penetration Testing に Deep Dive してみる
asanoharuki
1
1.3k
Featured
See All Featured
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
The Pragmatic Product Professional
lauravandoore
37
7.5k
Large-scale JavaScript Application Architecture
addyosmani
516
110k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.7k
What's in a price? How to price your products and services
michaelherold
247
13k
Designing for Timeless Needs
cassininazir
1
530
Embracing the Ebb and Flow
colly
88
5.2k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
610
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
460
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.5k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Transcript
͍͔ʹCloudEndpointsΛΊ SwaggerΛѪ͢ΔΑ͏ʹͳ͔ͬͨ Θ͔Ί ·͞ͻΖ
Θ͔Ί ·͞ͻΖ @v vakame TypeScript Masahiro Wakame DefinitelyTyped appengine/go photo
from golang.org/doc/gopher/
Google API Discovery Service ୭͔ͬͯΔʁ
APIs Explorer is ਆ https://developers.google.com/apis-explorer/
APIs Explorer • ୭Ͱ؆୯ʹ͑Δ • ࣮ࡍͷAPI͕ୟ͔ΕΔ • ݁ՌΛڞ༗͍͢͠ • ίʔυ͔ΒUI͕ੜ͞Ε͍ͯΔ
• ίʔυ == CloudEndpoints CloudEndpoints→APIs Explorer
but…
GoogleͷҋͷྖҬ Ϣʔβ GAE ҋ path mapping request format VersionସޙreqΛͳ͔ͬͨࣄʹ custom
domainෆՄ go-endpoints͕ͨ·ʹͭΒ͍
Swagger ͦ͜ͰSwaggerͰ͢Α
✨swagger✨ • Swagger͕Ұ൪ྑͦ͞͏ʂ • RAML, JSON Schema etc… • Open
API Initiativeൃ • Swagger༷Λbaseʹ • ͍ͷʹר͔Ε͍ͨ • Qiitaʹൺֱ·ͱΊ goo.gl/BLS3uH
ucon࡞Δ طଘ࣮ௐ͚ͨͲ ࣗͰ࡞Δ͜ͱʹͨ͠ https://github.com/favclip/ucon
લఏ • appengineറΓʹ͠ͳ͍ • ͱ͍͑appengineͰ͑ͳ͍ͱࠔΔ • net/httpʹ͍ۙAPI • ॊೈੑ •
go-endpointsͱͷޓੑ • swaggeropt-in ͍ͬͯ͘
໊͚ a2c͞Μ uconͱ ໊͚Α͏ʂ
ܾΊͨޙ a2c͞Μ ←ΏΔ͞ͳ͍
ಈ͘σϞ ؒʹ߹Θͳ͍͔ͱࢥͬͨΒ ͍ͭͷؒʹ͔ͬͯ͋ͬͨ
TODO • github.com/vvakame/ucon-todo • ucon-todo.appspot.com/ • ucon-todo.appspot.com/swagger-ui/ • ࣭ૉ ಈ͘ʂ
ར༻ࣄྫ
ར༻αΠτ • favclip • ٕज़ॻయ • TopgateࣾͰࠓޙ͍ͬͯͣ͘…
༷հ
ucon Features • net/http ͱͷྨࣅੑ • Routing • Method, Path
Matching • Middleware • Bubble • Dependency Injection • Plugin
API likes net/http ucon.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {})
API likes net/http ucon.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {})
Routing ucon.HandleFunc(“*", “/“, … ucon.HandleFunc(“OPTIONS", “/“, … ucon.HandleFunc(“GET", “/“, …
ucon.HandleFunc(“POST", “/“, … ucon.HandleFunc(“GET", “/api/user“, … ucon.HandleFunc(“GET", “/api/user/me“, … ucon.HandleFunc(“GET", “/api/user/{id}“, …
Routing rule • METHOD͕Ұக͢Δ • * ࢦఆՄ ݫີҰக༏ઌ • Request
Path͕Ұக͢Δ • ෳީิ͋Δ߹ΑΓ͍અҰக • Request GET /api/user/123 • GET /api/user/{id} • ❌ GET /api/user • ઌొ༏ઌ
Middleware • 1 requestຖͷॲཧʹհೖ • JavaͰ͍͏ServletFilter • ASP.NET MVCͰ͍͏Filter •
Logging, DI, CORS༻Header, error→JSONม etc, etc…
Middleware Middleware Middleware Middleware Handler ServeHTTP DI Cache-Control Cookie appengine.Context
etc, etc… CORS Header Path, Query, Body → JSON *http.Request http.ResponseWriter
Middleware type MiddlewareFunc func(b *Bubble) error type Bubble struct {
R *http.Request W http.ResponseWriter Context context.Context RequestHandler interface{} ArgumentTypes []reflect.Type Arguments []reflect.Value Returns []reflect.Value } func (b *Bubble) Next() error { … } func (b *Bubble) do() error { hv := reflect.ValueOf(b.handler()) … b.Returns = hv.Call(b.Arguments) return nil } var httpReqType = reflect.TypeOf((*http.Request)( var httpRespType = reflect.TypeOf((*http.Response func HTTPRWDI() MiddlewareFunc { return func(b *Bubble) error { for idx, argT := range b.ArgumentTypes { if argT == httpReqType { b.Arguments[idx] = reflect.ValueOf(b.R) continue } if argT == httpRespType { b.Arguments[idx] = reflect.ValueOf(b.W) continue } } return b.Next() } }
built-in middleware • HTTPRWDI • *http.Request, http.ResponseWriterͷDI • NetContextDI •
net/contextͷContextΛDI
built-in middleware • RequestObjectMapper • path parameter, query paramter, post
bodyΛObjectʹม͠DI • ResponseMapper • Handler͕returnͨ͠ObjecterrorΛ JSONʹม
Plugin • ϓϩηεىಈ࣌1ճ͚ͩಈ࡞ • શHandlerͷࠪ • Handler→Pluginؒͷͷୡػߏ • swaggerplugin •
શHandlerͷใ͔Βॲཧ • swagger.jsonग़ྗ༻HandlerͷՃ
Plugin type pluginContainer struct { base interface{} } type
HandlersScannerPlugin interface { HandlersScannerProcess(m *ServeMux, rds []*RouteDefinition) error } type RouteDefinition struct { Method string PathTemplate *PathTemplate HandlerContainer HandlerContainer } func (m *ServeMux) Prepare() { for _, plugin := range m.plugins { used := false if sc := plugin.HandlersScanner(); sc != nil { err := sc.HandlersScannerProcess(m, m.router.handlers) if err != nil { panic(err) } used = true } if !used { panic(fmt.Sprintf("unused plugin: %#v", plugin)) } } }
Plugin type pluginContainer struct { base interface{} } type
HandlersScannerPlugin interface { HandlersScannerProcess(m *ServeMux, rds []*RouteDefinition) error } type RouteDefinition struct { Method string PathTemplate *PathTemplate HandlerContainer HandlerContainer } func (m *ServeMux) Prepare() { for _, plugin := range m.plugins { used := false if sc := plugin.HandlersScanner(); sc != nil { err := sc.HandlersScannerProcess(m, m.router.handlers) if err != nil { panic(err) } used = true } if !used { panic(fmt.Sprintf("unused plugin: %#v", plugin)) } } }
swagger plugin usage swPlugin := swagger.NewPlugin(…) ucon.Plugin(swPlugin) s := &fooService{}
tag := swPlugin.AddTag(&swagger.Tag{Name: "Foo", Description: ""}) var info *swagger.HandlerInfo info = swagger.NewHandlerInfo(s.List) ucon.Handle("GET", "/api/foo/{id}", info) info.Description, info.Tags = "FooΛ1݅औಘ͢Δ", []string{tag.Name} … type IntIDRequest struct { ID int64 `json:"id,string"` } func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … }
swagger plugin usage swPlugin := swagger.NewPlugin(…) ucon.Plugin(swPlugin) s := &fooService{}
tag := swPlugin.AddTag(&swagger.Tag{Name: "Foo", Description: ""}) var info *swagger.HandlerInfo info = swagger.NewHandlerInfo(s.List) ucon.Handle("GET", "/api/foo/{id}", info) info.Description, info.Tags = "FooΛ1݅औಘ͢Δ", []string{tag.Name} … type IntIDRequest struct { ID int64 `json:"id,string"` } func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … } go-endpointsͱͷޓੑ!
ίʔυنͷ • ຊମ 1339ߦ • ls | grep .go |
grep -v _test.go | xargs wc -l • swaggerϓϥάΠϯ 1138ߦ • find ./swagger -type f | grep .go | grep -v sample | grep -v _test.go | xargs wc -l
એ
6/25 () 11:00ʙ17:00 ळ༿ݪ ௨ӡձؗ ٕज़ॻΦϯϦʔଈചձ ݸਓ੍࡞ͷٕज़ॻ✕56ஂମ techbookfest.org
ࣗલϥΠϒϥϦհ ͬͯΈͯͶʂ
GAE༻ϥΠϒϥϦ࡞ͬͯ·͢ • testerator github.com/favclip/testrator • UnitTestߴԽ • qbg github.com/favclip/qbg •
Datastore༻TypeSafeΫΤϦϏϧμ • smg github.com/favclip/smg • Search API༻TypeSafeϥού productionͰར༻தʂ
ͦͷଞϥΠϒϥϦ࡞ͬͯ·͢ • jwg github.com/favclip/jwg • JSON༻ͷTagͱ͔ࣗಈͰΔͭଞ • golidator github.com/favclip/golidator •
Validator ศར