ucon-ajn33

 ucon-ajn33

いかにCloudEndpointsをやめSwaggerを愛するようになったか ajn #33
http://gcpja.connpass.com/event/30761/

0e797080b64e6b03ed00964cf69b5058?s=128

Masahiro Wakame

June 08, 2016
Tweet

Transcript

  1. 6.
  2. 9.

    ✨swagger✨ • Swagger͕Ұ൪ྑͦ͞͏ʂ • RAML, JSON Schema etc… • Open

    API Initiativeൃ଍ • Swagger࢓༷Λbaseʹ • ௕͍΋ͷʹ͸ר͔Ε͍ͨ • Qiitaʹൺֱ·ͱΊ goo.gl/BLS3uH
  3. 19.

    ucon Features • net/http ͱͷྨࣅੑ • Routing • Method, Path

    Matching • Middleware • Bubble • Dependency Injection • Plugin
  4. 22.

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

    Routing rule • METHOD͕Ұக͢Δ • * ࢦఆ΋Մ ݫີҰக༏ઌ • Request

    Path͕Ұக͢Δ • ෳ਺ީิ͋Δ৔߹ΑΓ௕͍અҰக • Request GET /api/user/123 • GET /api/user/{id} • ❌ GET /api/user • ઌొ࿥༏ઌ
  6. 25.

    Middleware Middleware Middleware Middleware Handler ServeHTTP DI Cache-Control Cookie appengine.Context

    etc, etc… CORS Header Path, Query, Body → JSON *http.Request http.ResponseWriter
  7. 26.

    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()
 }
 }
  8. 28.

    built-in middleware • RequestObjectMapper • path parameter, query paramter, post

    bodyΛObjectʹม׵͠DI • ResponseMapper • Handler͕returnͨ͠Object΍errorΛ JSONʹม׵
  9. 30.

    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))
 }
 }
 }
  10. 31.

    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))
 }
 }
 }
  11. 32.

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

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

    ίʔυن໛ͷ࿩ • ຊମ 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
  14. 35.
  15. 38.

    GAE༻ϥΠϒϥϦ࡞ͬͯ·͢ • testerator github.com/favclip/testrator • UnitTestߴ଎Խ • qbg github.com/favclip/qbg •

    Datastore༻TypeSafeΫΤϦϏϧμ • smg github.com/favclip/smg • Search API༻TypeSafeϥού productionͰར༻தʂ