Top View


Author Yuhei Okazaki

Goaを使ったデザインファーストなAPIサーバ構築

2018/11/14

Goaとは

Goa Logo

公式サイト github

デザインファーストなmicroserviceフレームワークです。

どういった点がデザインファーストかと言うと、最初にDSLでAPIサーバの仕様や扱うリソース、対応する機能を定義し、これを元にソースコードの大半が自動生成される点です。自動生成されたソースコード中に、リクエストを受け付けた時の処理を記述するだけでAPIサーバが出来上がるので、処理ロジックに集中して開発することができます。

JWT認証等のセキュリティ機能を追加したり、O/Rマッパーを使用することもできます。Go言語なのでコンパイル時の型チェックがあったり、golangのエコシステム(数多くのツールやライブラリ)を活用出来る点も嬉しいところです。

以下コマンドを実行することでGoaをインストールできます。

$ go get -u github.com/goadesign/goa/...

APIサーバを作ってみる

まずは、Workspace(今回は app というディレクトリ)を作成し、 my_app/design/design.go を作成・編集します。このファイルが、後に元にソースコードを自動生成する際のいわば設計図となります。

VSCode

今回はシンプルに User を取得するAPIサーバを作ることにしました。

package design
 
 import (
 . "github.com/goadesign/goa/design"
 . "github.com/goadesign/goa/design/apidsl"
 )
 
 var \_ = API("MyApp", func() {
 Title("My App")
 Description("This is api server for my application.")
 Scheme("http")
 Host("localhost:8080")
 BasePath("/api/v1")
 })
 
 var \_ = Resource("user", func() {
 BasePath("/users")
 DefaultMedia(UserMedia)
 
 Action("list", func() {
 Description("Get all users")
 Routing(GET("/"))
 Response(OK, func() {
 Media(CollectionOf(UserMedia, func() {
 View("default")
 }))
 })
 Response(NotFound)
 })
 
 Action("show", func() {
 Description("Get user by id")
 Routing(GET("/:userID"))
 Params(func() {
 Param("userID", Integer, "User ID")
 })
 Response(OK)
 Response(NotFound)
 })
 })
 
 // UserMedia defines the media type used to render bottles.
 var UserMedia = MediaType("application/vnd.goa.example.user+json", func() {
 Description("A user of my application")
 Attributes(func() {
 Attribute("id", Integer, "Unique user ID")
 Attribute("email", String, "User's email")
 Attribute("last\_name", String, "User's last name")
 Attribute("first\_name", String, "User's first name")
 Required("id", "email", "last\_name", "first\_name")
 })
 View("default", func() {
 Attribute("id")
 Attribute("email")
 Attribute("last\_name")
 Attribute("first\_name")
 })
 })

コマンドを実行して、ソースコードを自動生成します。

$ goagen bootstrap -d github.com/yuuu/my\_app/design

VSCode

自動生成された user.go にリクエスト時の処理を記述します。

package main
 
 import (
 "github.com/goadesign/goa"
 "github.com/yuuu/my\_app/app"
 )
 
 // UserController implements the user resource.
 type UserController struct {
 \*goa.Controller
 }
 
 // NewUserController creates a user controller.
 func NewUserController(service \*goa.Service) \*UserController {
 return &UserController{Controller: service.NewController("UserController")}
 }
 
 var users = []\*app.GoaExampleUser{
 &app.GoaExampleUser{ID: 1, Email: "user1@example.com", LastName: "Fusic", FirstName: "Taro"},
 &app.GoaExampleUser{ID: 2, Email: "user2@example.com", LastName: "Fusic", FirstName: "Jiro"},
 }
 
 // List runs the list action.
 func (c \*UserController) List(ctx \*app.ListUserContext) error {
 // UserController\_List: start\_implement
 
 // Put your logic here
 // 実際にはデータベース等から読み出す
 res := users
 //res := app.GoaExampleUserCollection{}
 return ctx.OK(res)
 // UserController\_List: end\_implement
 }
 
 // Show runs the show action.
 func (c \*UserController) Show(ctx \*app.ShowUserContext) error {
 // UserController\_Show: start\_implement
 
 // Put your logic here
 // 実際にはデータベース等から読み出す
 res := users[ctx.UserID]
 //res := &app.GoaExampleUser{}
 return ctx.OK(res)
 // UserController\_Show: end\_implement
 }

APIサーバへリクエストしてみる

go run してAPIサーバを起動します。

$ go run \*.go

curl でリクエストすると、レスポンスに User の情報がセットされていることがわかります。

$ curl localhost:8080/api/v1/users/
 [{"email":"user1@example.com","first\_name":"Taro","id":1,"last\_name":"Fusic"},{"email":"user2@example.com","first\_name":"Jiro","id":2,"last\_name":"Fusic"}]
 
 $ curl localhost:8080/api/v1/users/0
 {"email":"user1@example.com","first\_name":"Taro","id":1,"last\_name":"Fusic"}
 
 $ curl localhost:8080/api/v1/users/1
 {"email":"user2@example.com","first\_name":"Jiro","id":2,"last\_name":"Fusic"}

今後の展望

今回はデータベース等を使用せずにAPIサーバの動作確認をしていますが、実際にはデータベースに対してCRUD操作する場合がほとんどなのでO/Rマッパーを使うよう設定する必要があります。また、認証機能(JWT等)を使えるようにする必要があります。

Vue.jsと組み合わせて使うことを想定すると、クロスオリジン要求に対応するよう設定することも必要です。

このあたりは、次回解説したいと思います。

Yuhei Okazaki

Yuhei Okazaki

Twitter X

2018年の年明けに組込み畑からやってきた、2児の父 兼 Webエンジニアです。 mockmockの開発・運用を担当しており、組込みエンジニア時代の経験を活かしてデバイスをプログラミングしたり、簡易的なIoTシステムを作ったりしています。主な開発言語はRuby、時々Go。

Related Posts

sam local start-apiでDynamoDB Localをゆるふわに使う
shiro seike / せいけ しろう / 清家 史郎

shiro seike / せいけ しろう / 清家 史郎

2020/12/30


aws-sdk-goを使ったAthena API
shiro seike / せいけ しろう / 清家 史郎

shiro seike / せいけ しろう / 清家 史郎

2020/12/21




DATA-DOG/go-sqlmockを使ってGormDBをmockする
shiro seike / せいけ しろう / 清家 史郎

shiro seike / せいけ しろう / 清家 史郎

2020/12/02