Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
141
Help us understand the problem. What is going on with this article?
@ytkhs

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

More than 3 years have passed since last update.

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

141
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ytkhs
A web developer based in Tokyo, Yokohama and Niigata.

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
141
Help us understand the problem. What is going on with this article?