以前の記事(GAE(Google App Engine) で Golang 使った REST API)を作りましたが、今回は echo (Golang 用のフレームワーク) を使った REST API を作ってみようと思います。
Google App Engine 用のサンプルはこちらを参考にしました。
プログラム構成
基本的にはサンプルプログラム通りですが、root ディレクトリに通常の go コマンドからの起動用のコード(app-standalone.go)を置いて本体のプログラムは gae_echo ディレクトリ直下に配置しています。
$ tree
├── README.md
├── app-standalone.go
└─── gae_echo
├── app-engine.go
├── app-engine.yaml
├── app.go
└── users.go
ソースコード
通常の go コマンドからの起動用のプログラムと echo インスタンス生成用のコードになります。
package gae_echo
// reference our echo instance and create it early
var e = createMux()
func Start() {
e.Logger.Fatal(e.Start(":8080"))
}
通常の go コマンドからの起動用のプログラムと echo インスタンス生成用のコードになります。
package gae_echo
import (
"net/http"
"github.com/labstack/echo"
)
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
http.Handle("/", e)
return e
}
ユーザー情報(IDと名前だけだけど、、、)を登録/参照する API の本体で、データをメモリ上に保存します。
package gae_echo
import (
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
type (
user struct {
ID string `json:"id"`
Name string `json:"name"`
}
)
var (
users map[string]user
)
func init() {
users = map[string]user{
"1": user{
ID: "1",
Name: "Wreck-It Ralph",
},
}
// hook into the echo instance to create an endpoint group
// and add specific middleware to it plus handlers
g := e.Group("/users")
g.Use(middleware.CORS())
g.POST("", createUser)
g.GET("", getUsers)
g.GET("/:id", getUser)
}
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.Param("id")])
}
サンプルの yaml から必要な部分だけ抜き出しています。
application: hello-gae-go
version: 1
runtime: go
api_version: go1.8
handlers:
- url: /.*
script: _go_app
サンプルはうまく動かなかったので、ちょっと変更しています。
// +build !appengine,!appenginevm
package main
import (
"github.com/ynozue/hellow-gae-go/gae_echo"
)
func main() {
gae_echo.Start()
}
動作確認
起動
$ goapp serve gae_echo/app-engine.yaml
INFO 2017-10-15 13:47:45,383 devappserver2.py:115] Skipping SDK update check.
INFO 2017-10-15 13:47:45,528 api_server.py:299] Starting API server at: http://localhost:57500
INFO 2017-10-15 13:47:45,539 dispatcher.py:224] Starting module "default" running at: http://localhost:8080
INFO 2017-10-15 13:47:45,541 admin_server.py:116] Starting admin server at: http://localhost:8000
curl での動作確認
一覧参照
$ curl http://localhost:8080/users | python -m json.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 74 100 74 0 0 3755 0 --:--:-- --:--:-- --:--:-- 3894
{
"1": {
"id": "1",
"name": "Wreck-It Ralph"
}
登録
$ curl -X POST \
-H 'Content-Type: application/json' \
-d '{"id":"2","name":"Joe Smith"}' \
http://localhost:8080/users | python -m json.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 58 100 29 100 29 896 896 --:--:-- --:--:-- --:--:-- 906
{
"id": "2",
"name": "Joe Smith"
}
一覧参照(登録後)
$ curl http://localhost:8080/users | python -m json.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 74 100 74 0 0 3755 0 --:--:-- --:--:-- --:--:-- 3894
{
"1": {
"id": "1",
"name": "Wreck-It Ralph"
},
"2": {
"id": "2",
"name": "Joe Smith"
}
}
詳細参照
$ curl http://localhost:8080/users/2 | python -m json.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 29 100 29 0 0 2759 0 --:--:-- --:--:-- --:--:-- 2900
{
"id": "2",
"name": "Joe Smith"
}
まとめ
net/http パッケージを利用するよりかは POST データのパースや URI に対応するプログラムの切り分けなどが簡単にできました。
echo には色々な機能が用意されてるみたいなので、サンプルを試しながら調べていこうかと思います。