goaでAPIを作ってみる

goaを作ってAPIの入り口まで作ってみます。DBまでつないで本格的に作るのは後日。。。

go get -u github.com/goadesign/goa/...
  • 後は自分のプロジェクト内でdesign/design.goを作成し編集します。

変数名などを少し変えたのと、list出力してくれるAPIを追加してます。

package design // The convention consists of naming the design
import (
    . "github.com/goadesign/goa/design" // Use . imports to enable the DSL
    . "github.com/goadesign/goa/design/apidsl"
)

var _ = API("myapi", func() { // API defines the microservice endpoint and
    Title("API to through MyAPI")                    // other global properties. There should be one
    Description("API to through My API without CORS") // and exactly one API definition appearing in
    Scheme("http")                                        // the design.
    Host("localhost:8080")
    // CORSポリシーの定義  ←ここ追加
    Origin("*", func() {
        //クライアントに公開された1つ以上のヘッダー
        Expose("X-Time")
        // 1つまたは複数の許可されたHTTPメソッド
        Methods("GET", "POST", "PUT", "DELETE", "OPTIONS")
        //プリフライト要求応答をキャッシュする時間
        MaxAge(600)
        // Access-Control-Allow-Credentialsヘッダーを設定する
        Credentials()
    })
})

var _ = Resource("station", func() { // Resources group related API endpoints
    BasePath("/stations")      // together. They map to REST resources for REST
    DefaultMedia(StationMedia) // services.

    Action("show", func() { // Actions define a single API endpoint together
        Description("Get station by id") // with its path, parameters (both path
        Routing(
            GET("/:stationID"))
        Params(func() { // (shape of the request body).
            Param("stationID", Integer, "Station ID")
        })
        Response(OK, StationMedia) // Responses define the shape and status code
        Response(NotFound)         // of HTTP responses.
    })
    Action("list", func() { // Actions define a single API endpoint together         // ←ここ丸々追加。リソース一覧取得用
        Description("Get stations") // with its path, parameters (both path
        Routing(
            GET("/")) // parameters and querystring values) and payload
        Response(OK, CollectionOf(StationMedia)) // Responses define the shape and status code    // ←配列を返したい場合CollectionOfを使う
        Response(NotFound)                       // of HTTP responses.
    })
})

// StationMedia defines the media type used to render bottles.
var StationMedia = MediaType("application/vnd.myapi.station+json", func() {
    Description("A station of mine")
    Attributes(func() { // Attributes define the media type shape.
        Attribute("id", Integer, "Unique station ID")
        Attribute("href", String, "API href for making requests on the station")
        Attribute("name", String, "Name of station")
        Required("id", "href", "name")
    })
    View("default", func() { // View defines a rendering of the media type.
        Attribute("id")   // Media types may have multiple views and must
        Attribute("href") // have a "default" view.
        Attribute("name")
    })
})

ここまでできたら

goagen bootstrap  -d github.com\***\***\design

↑自分のプロジェクトディレクトリに合わせてください

上記の例だとstation.goというファイルができるのでその中を編集 // StationController_List: start_implement と書かれている下から追加する感じです。

// List runs the list action.
func (c *StationController) List(ctx *app.ListStationContext) error {
    // StationController_List: start_implement

    res := make(app.MyapiStationCollection, 2)
    st := []app.MyapiStation{{    // ←配列の中身は適当に作成してます。実際はDBから取得してfor分などで代入
        ID:   1,
        Name: "a",
        Href: "b",
    },
        {
            ID:   2,
            Name: "aa",
            Href: "bb",
        }}

    res[0] = &st[0]
    res[1] = &st[1]
    return ctx.OK(res)

    // StationController_List: end_implement
}

// Show runs the show action.
func (c *StationController) Show(ctx *app.ShowStationContext) error {
    // StationController_Show: start_implement

    station := app.MyapiStation{
        ID:   ctx.StationID,
        Name: fmt.Sprintf("Station #%d", ctx.StationID),
        Href: app.StationHref(ctx.StationID),
    }

    return ctx.OK(&station)

    // StationController_Show: end_implement
}

上記でstationオブジェクトの型になっているapp.MyapiStationは design.goで宣言されているMediaTypeの引数に依存してます。

var StationMedia = MediaType("application/vnd.myapi.station+json", func() {

↑のvnd.と+jsonの間です。

  • ここまで来たら
go build -o station.exe

して実行ファイルを作って、できたファイルをそのまま実行しましょう。

http://localhost:8080/stationsにアクセスするとさっき配列に入れた値が表示されると思います。