UPDATE 2016/06/12
2.0がリリースされました。
v2.0.1でやってみたところこの記事内容は動くようですが、少しだけ変更点があるようです。
https://echo.labstack.com/guide/migrating
また、ローカルでバージョンアップするには以下のようにします。
# テストのフレームワークがないよと怒られるので事前に取得します。
go get github.com/stretchr/testify
# echoのアップデート
go get -u github.com/labstack/echo/...
GoでJSONを返すAPIサーバを作ってみたかったので調べました。
echoとは
Goで作られている軽量なフレームワークで、他のものに比べて現在も開発が活発です。最新版はv1.4ですが、v2.0.0betaが出ているので近々バーションアップされるようです。
Echo is a fast and unfancy HTTP server framework for Go (Golang). Up to 10x faster than the rest. https://labstack.com/echo
https://github.com/labstack/echo
Installation
チュートリアルに従ってやってみます。
# echoのインストール
go get github.com/labstack/echo/...
# プロジェクトのディレクトリを作ります
cd $GOPATH/src
mkdir echo-sample
cd echo-sample
app.goというファイルを作ります。
package main
import (
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/engine/standard"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Run(standard.New(":1323"))
}
で、実行。
go run app.go
# 何も表示がなくわかりづらいですが、http://localhost:1323 に'Hello, world'と表示されます
GoogleAppEngineで動かす
ローカル環境で動かすのは簡単なのですが、GAEで動かすのにルーティングがうまくいかず悩んでいたら普通に解説がありました(--#)
これに沿って行きます。
JSONを返すAPIと静的なファイル配信
package main
// 起点となるファイルです
var e = createMux()
// +build !appengine,!appenginevm
package main
import (
"github.com/labstack/echo"
"github.com/labstack/echo/engine/standard"
"github.com/labstack/echo/middleware"
)
// ログの設定や静的ファイルの場所指定などをしています
func createMux() *echo.Echo {
e := echo.New()
e.Use(middleware.Recover())
e.Use(middleware.Logger())
e.Use(middleware.Gzip())
e.Use(middleware.Static("public"))
return e
}
func main() {
e.Run(standard.New(":8080"))
}
publicを静的ファイルの場所としたので、HTMLでも作っておきます
<h1>HELLO, ECHO!</h1>
Userの情報をJSONで返します
package main
import (
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/engine/standard"
"github.com/rs/cors"
)
// UserのJSONの形を指定します。
type (
user struct {
ID string `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
)
var (
users map[string]user
)
func init() {
// 初期データを登録してみます
users = map[string]user{
"1": user{
ID: "1",
Name: "ジョナサン・ジョースター",
Age: 20,
},
"2": user{
ID: "2",
Name: "ディオ・ブランドー",
Age: 21,
},
}
g := e.Group("/users")
g.Use(standard.WrapMiddleware(cors.Default().Handler))
g.POST("", createUser)
g.GET("", getUsers)
g.GET("/:id", getUser)
}
// Userの作成、一覧、詳細です
func createUser(c echo.Context) error {
u := new(user)
if err := c.Bind(u); err != nil {
return err
}
users[u.ID] = *u
return c.JSON(http.StatusCreated, u)
}
func getUsers(c echo.Context) error {
return c.JSON(http.StatusOK, users)
}
func getUser(c echo.Context) error {
return c.JSON(http.StatusOK, users[c.P(0)])
}
GoogleAppEngine用のルーティング
AppEngine用には設定はあまりしなくて良いようです。
// +build appengine
package main
import (
"github.com/labstack/echo"
"github.com/labstack/echo/engine/standard"
"net/http"
)
func createMux() *echo.Echo {
e := echo.New()
// note: we don't need to provide the middleware or static handlers, that's taken care of by the platform
// app engine has it's own "main" wrapper - we just need to hook echo into the default handler
s := standard.New("")
s.SetHandler(e)
http.Handle("/", s)
return e
}
// main()も書かなくて良い
設定ファイルも追加します
runtime: go
api_version: go1
handlers:
- url: /
mime_type: text/html
static_files: public/index.html
upload: public/index.html
- url: /favicon.ico
mime_type: image/x-icon
static_files: public/favicon.ico
upload: public/favicon.ico
- url: /scripts
mime_type: text/javascript
static_dir: public/scripts
- url: /.*
script: _go_app
GoogleAppEngineにデプロイ
SDKのインストールは割愛します。ダウンロードはこちらから
https://cloud.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go
SDKを使ってローカルで起動してみましょう。
ファイル構成はこんな感じです。
.
├── app-engine.go
├── app-standalone.go
├── app.go
├── app.yaml
├── public
│ └── index.html
└── users.go
goapp serve
# can't find import: "github.com/rs/cors" と言われたのでインストールします
go get github.com/rs/cors
# retry
goapp serve
> INFO 2016-04-24 07:25:34,339 admin_server.py:116] Starting admin server at: http://localhost:8000
# 無事に起動したようなので、http://localhost:8080 にアクセスすると <h1>HELLO, ECHO!</h1> と表示されます
# JSONを取得してみます
curl -s http://localhost:8080/users/1 | jq
{
"id": "1",
"name": "ジョナサン・ジョースター",
"age": 20
}
できているようですね。
Googleのクラウドコンソールからプロジェクトを作成し、プロジェクトIDを控えます
https://console.cloud.google.com/
そして、以下のコマンドを実行すると認証画面が出るので許可します。
cd $GOPATH/src
appcfg.py -A <YOUR_PROJECT_ID> -V v1 update echo-sample/
> 04:28 PM Deployment successful.
成功したので、http://YOUR_PROJECT_ID.appspot.com にアクセスして、HELLO,ECHO!と表示されていればOKです。
JSONのAPIも確認してみましょう。
curl -s <YOUR_PROJECT_ID>.appspot.com/users | jq
{
"1": {
"id": "1",
"name": "ジョナサン・ジョースター",
"age": 20
},
"2": {
"id": "2",
"name": "ディオ・ブランドー",
"age": 21
}
}
まとめ
軽量フレームワークechoを使ってJSONを返すAPIを作成し、GoogleAppEngineで動かしてみました。JSONを返すだけであれば、標準ライブラリのnet/httpでも問題ありませんが、echoは開発が活発で4000starほどついているので試してみました。近々2.0も出るようなので、また試してみたいと思います。