追記 2016/11/17
最新のechoではこの記事の内容は動作しません
echoの2.0がreleaseされてfasthttpでも使えるようになってました。
echo.HandlerFunc
もcontext.Context
に対応していてAppEngineのサービスを呼び出すときにミドルウェア一つでそのままcontextを突っ込めば動くようになってるのが自分的には嬉しいです。
echo
GoのWebFrameworkです。軽量で高速な動作で標準のnet/httpとfasthttpの両方に対応しています。
Install
go get github.com/labstack/echo/...
go get google.golang.org/appengine/...
HelloWorld
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
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に流せるようにしたいなと思ってるのですが
どうすればいいかなで悩んでます。