LoginSignup
165
140

More than 5 years have passed since last update.

Go製のフレームワークechoを使ってJSONを返すWebサーバーを作り、GoogleAppEngineで動かす

Last updated at Posted at 2016-04-24

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というファイルを作ります。

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で動かすのにルーティングがうまくいかず悩んでいたら普通に解説がありました(--#)

https://labstack.com/echo/recipes/google-app-engine

これに沿って行きます。

JSONを返すAPIと静的なファイル配信

app.go
package main
// 起点となるファイルです
var e = createMux()
app-standalone.go
// +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でも作っておきます

public/index.html
<h1>HELLO, ECHO!</h1>

Userの情報をJSONで返します

users.go
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用には設定はあまりしなくて良いようです。

app-engine.go
// +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()も書かなくて良い

設定ファイルも追加します

app.yaml
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も出るようなので、また試してみたいと思います。

165
140
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
165
140