LoginSignup
22
21

More than 5 years have passed since last update.

go-endpointsを触ってみた

Last updated at Posted at 2013-11-12

go-endpoints

AppEngineではRESTサーバと、そのクライアントライブラリを簡単に作るための仕組みとして、
Google Cloud Endpointsを機能として提供しています。

現状は公式ではGAE/J、GAE/P(Python)のみ利用可能で
一度個人的にGAE/Jで使ってみたのですが、
Spin-upの問題などで、ちょいちょいスピードが気になっていました。

そこである方から、Go言語のサードパーティ製Clound Endpoints実装があることを教えていただいたので、
ちょろちょろ書いてみたいと思います。(ほとんどreadmeと同じですが...)

Intro

go-endpointsはGo言語のサードパーティ製Clound Endpoints実装で、
Cloud Endpointsで利用させるGoogle Discovery Service用のJSONの作成や、
APIの作成フレームワークを提供します。

Install

Goや、appengine-goのインストールは省きます。
まずgo-endpointsを取得します。

go get github.com/crhym3/go-endpoints/endpoints

多分取得時に以下の様なエラーが吐かれますが、特に問題ないです。

package appengine: unrecognized import path "appengine"
package appengine/user: unrecognized import path "appengine/user"
package appengine_internal/user: unrecognized import path "appengine_internal/user"

現状go-endpointsはappengineパッケージに依存していますが(依存していないforkもある)、
appengineパッケージは通常dev serverにより提供されるので、存在しなくても動きます。

使用方法

リクエストの受取用とレスポンスの返却用structの作成

まず、データの送受信用structを作成します。

このstructはgo-endpoints側でencoding/jsonパッケージにてstruct ←→ JSONの変換をされます。
必要であればencoding/jsonを利用する際に使う、field tagをつけておきます。
もちろん更に必要であれば、Datastore用のfield tagもつけておきます。

送信(Response)用struct.go
type Greeting struct {
  Key     string         `json:"id" datastore:"-"`
  Author  string         `json:"author"`
  Content string         `json:"content" datastore:",noindex"`
  Date    time.Time      `json:"date"`
}

type GreetingList struct {
  Items []*Greeting       `json:"items"`
}

またgo-endpointsでもfield tagを提供していて、そのjson fieldの必須/非必須、デフォルト値、説明等を定義できます。
※ただ自動でデフォルト値を入れてくれたり、チェックをしてくれる感じでは無い気がする... api explorerでの説明に利用しているのみ??

受信(Request)用struct.go
type GreetingSearchReq struct {
  Query string      `json:"q" endpoints:"req,required, desc=The query string"`
  Limit int         `json:"limit" endpoints:"d=10,min=1,max=100,desc=The limit search result count"`
}

細かいfiled tagの説明はここにありますが 、reqとrequiredがコード中にはあるなど微妙に揺れている気も...

サービスの作成

サービスは実際のAPIの送受信部分の実装を行います。

Service.go
import "github.com/crhym3/go-endpoints/endpoints"

type GreetingService struct {
}

// List responds with a list of all greetings ordered by Date field.
// Most recent greets come first.
func (gs *GreetingService) Search(r *http.Request, req *GreetingSearchReq, resp *GreetingsList) error {

  if req.Limit <= 0 {
    req.Limit = 10
  }

  c := endpoints.NewContext(r) //endpoints.Contextはappengine.Contextを持っている

  //なんかゴニョゴニョして、greets []*Greetingを取得

  resp.Items = greets
  return nil
}

サービスでは任意のメソッド名で

  • 第一引数が*http.Request
  • 第二引数が受信用のstruct
  • 第三引数が送信用のstruct
  • 返却値がerror

を定義します。

サービスの登録

サービスが作成できたら、登録をおこないます。

main.go

import "github.com/crhym3/go-endpoints/endpoints"

func init() {
  //サービスのインスタンスを作って RegisterServiceを呼び出し
  greetService := &GreetingService{}

  api, err := endpoints.RegisterService(greetService, "greeting", "v1", "Greetings API", true)
  if err != nil {
    panic(err.Error())
  }

  //APIは一つづつ登録していく
  info := api.MethodByName("Search").Info()
  info.Name, info.HttpMethod, info.Path, info.Desc =
    "greets.list", "GET", "greetings", "Search most recent greetings."

  endpoints.HandleHttp()
}

なお上記のinfo.Pathには/greetings/{id}などのURLパターン(って言い方で合ってる?)も利用可能です。

app.yamlの設定

あとはyamlにendpointsの設定をすれば完了です。


application: my-app-id
version: v1
threadsafe: true

runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app

# ここが絶対に必要
- url: /_ah/spi/.*
  script: _go_app

叩く

あとはdev serverを起動して、localhost:8080/_ah/api/explorerとかにアクセスすれば、試すことが可能です。

API Client Libraryの作成

大体ここ読めばok
※個人的にjsクライアントしか使わなかったので試してないですごめんなさい探さないでください。

その他

大体のことはパッケージドキュメントサンプルコード読むとわかると思います。

OAuthを利用した、appengineでのユーザ認証なども利用可能です。

気になりごと

現状だと、errorを返却した場合は、必ずHTTP Statusが400で返されます。
一応Pull Req送っているので取り込まれたら、変更することも可能になるはずです。(そしたらそのあたりも追記します。)

22
21
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
22
21