labstack/echoの2.0がreleaseされてたのでAppEngineで動かしてみる

  • 12
    いいね
  • 0
    コメント

追記 2016/11/17
最新のechoではこの記事の内容は動作しません

https://echo.labstack.com/

echoの2.0がreleaseされてfasthttpでも使えるようになってました。
echo.HandlerFunccontext.Contextに対応していてAppEngineのサービスを呼び出すときにミドルウェア一つでそのままcontextを突っ込めば動くようになってるのが自分的には嬉しいです。

echo

GoのWebFrameworkです。軽量で高速な動作で標準のnet/httpとfasthttpの両方に対応しています。

Install

go get github.com/labstack/echo/...
go get google.golang.org/appengine/...

HelloWorld

app.yaml
runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app
server.go
package main

import (
    "net/http"
    "github.com/labstack/echo"
    "github.com/labstack/echo/engine/standard"
)

func init() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    s := standard.New("")
    s.SetHandler(e)
    http.Handle("/", s)
}

goapp serveで開発サーバーを立ち上げれます
http://localhost:8080にアクセスしてみたらHello, World!と表示されます

echo.ContextでAppEngineのサービスにアクセスできるようにする

v1の頃は以下のように ハンドラ内でappengine.NewContextを呼び出してDatastoreやURLFetchを使ってました。

func (c *echo.Context) error {
    ctx := appengine.NewContext(c.Request())
    log.Infof(ctx, "Top")
    return c.String(200, "Top")
}

v2からはHandler内では以下のように書けるようにできます。

func (c echo.Context) error {
    log.Infof(c, "Top")
    return c.String(200, "Top")
}

そのためにはミドルウェアを書きます

func AppContext() echo.MiddlewareFunc {
    return func(next echo.HandlerFunc) echo.HandlerFunc {
        return func(c echo.Context) error {
            if r, ok := c.Request().(*standard.Request); ok {
                c.SetContext(appengine.WithContext(c.Context(), r.Request))
            }
            return next(c)
        }
    }
}

func init() {
    e := echo.New()
    e.Use(AppContext())
    e.GET("/", func(c echo.Context) error {
        log.Infof(c, "Path: %s", c.Request().URL().Path())
        return c.String(http.StatusOK, "Hello, World!")
    })
    s := standard.New("")
    s.SetHandler(e)
    http.Handle("/", s)
}

これでどっちのコンテキストだっけなぁと悩む必要はなくなりました。
context.Context対応の恩恵はこれだけではなくキャンセル処理やタイムアウト処理も実装しやすくなると思います。

概要はこの辺を見るとよいかと https://blog.golang.org/context
(サンプルが古いSearchAPIを使ってて動かなかったけど)

まとめ

雑ですが試したリポジトリ
https://github.com/k2wanko-sandbox/appengine-echo

LoggerをLogAPIに流せるようにしたいなと思ってるのですが
どうすればいいかなで悩んでます。