Slide 1

Slide 1 text

͍͔ʹCloudEndpointsΛ΍Ί SwaggerΛѪ͢ΔΑ͏ʹͳ͔ͬͨ Θ͔Ί ·͞ͻΖ

Slide 2

Slide 2 text

Θ͔Ί ·͞ͻΖ @v vakame TypeScript Masahiro Wakame DefinitelyTyped appengine/go photo from golang.org/doc/gopher/

Slide 3

Slide 3 text

Google API Discovery Service ୭͔஌ͬͯΔʁ

Slide 4

Slide 4 text

APIs Explorer is ਆ https://developers.google.com/apis-explorer/

Slide 5

Slide 5 text

APIs Explorer • ୭Ͱ΋؆୯ʹ࢖͑Δ • ࣮ࡍͷAPI͕ୟ͔ΕΔ • ݁ՌΛڞ༗͠΍͍͢ • ίʔυ͔ΒUI͕ੜ੒͞Ε͍ͯΔ • ίʔυ == CloudEndpoints CloudEndpoints→APIs Explorer

Slide 6

Slide 6 text

but…

Slide 7

Slide 7 text

GoogleͷҋͷྖҬ Ϣʔβ GAE ҋ path mapping request format Version੾ସޙreqΛͳ͔ͬͨࣄʹ custom domainෆՄ go-endpoints͕ͨ·ʹͭΒ͍

Slide 8

Slide 8 text

Swagger ͦ͜ͰSwaggerͰ͢Α

Slide 9

Slide 9 text

✨swagger✨ • Swagger͕Ұ൪ྑͦ͞͏ʂ • RAML, JSON Schema etc… • Open API Initiativeൃ଍ • Swagger࢓༷Λbaseʹ • ௕͍΋ͷʹ͸ר͔Ε͍ͨ • Qiitaʹൺֱ·ͱΊ goo.gl/BLS3uH

Slide 10

Slide 10 text

ucon࡞Δ࿩ طଘ࣮૷ௐ΂͚ͨͲ ࣗ෼Ͱ࡞Δ͜ͱʹͨ͠ https://github.com/favclip/ucon

Slide 11

Slide 11 text

લఏ • appengineറΓʹ͸͠ͳ͍ • ͱ͸͍͑appengineͰ࢖͑ͳ͍ͱࠔΔ • net/httpʹ͍ۙAPI • ॊೈੑ • go-endpointsͱͷޓ׵ੑ • swagger͸opt-in ΍͍ͬͯ͘

Slide 12

Slide 12 text

໊෇͚਌ ๭a2c͞Μ uconͱ ໊෇͚Α͏ʂ

Slide 13

Slide 13 text

ܾΊͨޙ ๭a2c͞Μ ←ΏΔ͞ͳ͍

Slide 14

Slide 14 text

ಈ͘σϞ ؒʹ߹Θͳ͍͔ͱࢥͬͨΒ ͍ͭͷؒʹ͔΍ͬͯ͋ͬͨ

Slide 15

Slide 15 text

TODO • github.com/vvakame/ucon-todo • ucon-todo.appspot.com/ • ucon-todo.appspot.com/swagger-ui/ • ࣭ૉ ಈ͘ʂ

Slide 16

Slide 16 text

ར༻ࣄྫ

Slide 17

Slide 17 text

ར༻αΠτ • favclip • ٕज़ॻయ • Topgateࣾ಺Ͱ͸ࠓޙ࢖͍ͬͯ͘͸ͣ…

Slide 18

Slide 18 text

࢓༷঺հ

Slide 19

Slide 19 text

ucon Features • net/http ͱͷྨࣅੑ • Routing • Method, Path Matching • Middleware • Bubble • Dependency Injection • Plugin

Slide 20

Slide 20 text

API likes net/http ucon.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {})

Slide 21

Slide 21 text

API likes net/http ucon.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {})

Slide 22

Slide 22 text

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}“, …

Slide 23

Slide 23 text

Routing rule • METHOD͕Ұக͢Δ • * ࢦఆ΋Մ ݫີҰக༏ઌ • Request Path͕Ұக͢Δ • ෳ਺ީิ͋Δ৔߹ΑΓ௕͍અҰக • Request GET /api/user/123 • GET /api/user/{id} • ❌ GET /api/user • ઌొ࿥༏ઌ

Slide 24

Slide 24 text

Middleware • 1 requestຖͷॲཧʹհೖ • JavaͰ͍͏ServletFilter • ASP.NET MVCͰ͍͏Filter • Logging, DI, CORS༻Header, error→JSONม׵ etc, etc…

Slide 25

Slide 25 text

Middleware Middleware Middleware Middleware Handler ServeHTTP DI Cache-Control Cookie appengine.Context etc, etc… CORS Header Path, Query, Body → JSON *http.Request http.ResponseWriter

Slide 26

Slide 26 text

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()
 }
 }

Slide 27

Slide 27 text

built-in middleware • HTTPRWDI • *http.Request, http.ResponseWriterͷDI • NetContextDI • net/contextͷContextΛDI

Slide 28

Slide 28 text

built-in middleware • RequestObjectMapper • path parameter, query paramter, post bodyΛObjectʹม׵͠DI • ResponseMapper • Handler͕returnͨ͠Object΍errorΛ JSONʹม׵

Slide 29

Slide 29 text

Plugin • ϓϩηεىಈ࣌1ճ͚ͩಈ࡞ • શHandlerͷ૸ࠪ • Handler→Pluginؒͷ஋ͷ఻ୡػߏ • swagger͸plugin • શHandlerͷ৘ใ͔Βॲཧ • swagger.jsonग़ྗ༻Handlerͷ௥Ճ

Slide 30

Slide 30 text

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))
 }
 }
 }

Slide 31

Slide 31 text

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))
 }
 }
 }

Slide 32

Slide 32 text

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) { … }

Slide 33

Slide 33 text

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ͱͷޓ׵ੑ!

Slide 34

Slide 34 text

ίʔυن໛ͷ࿩ • ຊମ 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

Slide 35

Slide 35 text

એ఻

Slide 36

Slide 36 text

6/25 (౔) 11:00ʙ17:00 ळ༿ݪ ௨ӡձؗ ٕज़ॻΦϯϦʔଈചձ ݸਓ੍࡞ͷٕज़ॻ✕56ஂମ techbookfest.org

Slide 37

Slide 37 text

ࣗલϥΠϒϥϦ঺հ ࢖ͬͯΈͯͶʂ

Slide 38

Slide 38 text

GAE༻ϥΠϒϥϦ࡞ͬͯ·͢ • testerator github.com/favclip/testrator • UnitTestߴ଎Խ • qbg github.com/favclip/qbg • Datastore༻TypeSafeΫΤϦϏϧμ • smg github.com/favclip/smg • Search API༻TypeSafeϥού productionͰར༻தʂ

Slide 39

Slide 39 text

ͦͷଞϥΠϒϥϦ΋࡞ͬͯ·͢ • jwg github.com/favclip/jwg • JSON༻ͷTagͱ͔ࣗಈͰ΍Δ΍ͭଞ • golidator github.com/favclip/golidator • Validator ศར