$30 off During Our Annual Pro Sale. View Details »

ucon-ajn33

 ucon-ajn33

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

Masahiro Wakame

June 08, 2016
Tweet

More Decks by Masahiro Wakame

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

  3. Google API Discovery Service
    ୭͔஌ͬͯΔʁ

    View Slide

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

    View Slide

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

    View Slide

  6. but…

    View Slide

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

    View Slide

  8. Swagger
    ͦ͜ͰSwaggerͰ͢Α

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. ܾΊͨޙ
    ๭a2c͞Μ

    ←ΏΔ͞ͳ͍

    View Slide

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

    View Slide

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

    View Slide

  16. ར༻ࣄྫ

    View Slide

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

    View Slide

  18. ࢓༷঺հ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

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

    }

    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    }

    }

    }

    View Slide

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

    }

    }

    }

    View Slide

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

    }

    View Slide

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

    View Slide

  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

    View Slide

  35. એ఻

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide