これはなに?
- WebフレームワークBeegoを使ってAPIサーバを立ててみる記事
- 本記事では、BeegoインストールからbeeコマンドによるAPI構築まで試す
環境
- Go: 1.18.3
- Beego: 2.0.1
- Bee: 2.0.4
注意
2022年8月現在、beegoの公式Docsのドメインが以前の beego.me
から beego.vip
に変更になっているようなので注意。
以前のドメイン踏むと全く関係ないサイトに誘導されるので要注意。
v2.0.0以前のREADMEのCommunity欄 を見ると以前のドメインとなっている。
v2.0.3以降のREADMEのCommunity欄 では現在(2022年8月)のドメイン。
前準備
Docker環境整備
.
├── api
│ └── docker
│ └── Dockerfile
└── docker-compose.yml
FROM golang:1.18.3-alpine3.16
ENV ROOT /go
ENV CGO_ENABLED 0
WORKDIR ${ROOT}
RUN apk update && apk add --no-cache git
version: '3'
services:
api:
container_name: practice-beego-api
build:
context: .
dockerfile: ./api/docker/Dockerfile
ports:
- 18080:8080
env_file: ./api/.env
working_dir: /go
volumes:
- ./api:/go
command: >
sh
tty: true
コンテナ構築
# 構築
$ docker-compose up -d
# 確認
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------
practice-beego-api sh Up 0.0.0.0:18080->8080/tcp
Beego導入
Beegoインストール
コンテナ入って作業開始
$ docker exec practice-beego-api
Beegoのインストール
# インストール
$ go install github.com/beego/bee/v2@latest
# 確認
$ bee version
2022/06/15 00:05:14.990 [D] init global config instance failed. If you do not use this, just ignore it. open conf/app.conf: no such file or directory
2022/06/15 00:05:15 INFO ▶ 0001 Getting bee latest version...
2022/06/15 00:05:15 INFO ▶ 0002 Your bee are up to date
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.4
├── GoVersion : go1.18.3
├── GOOS : linux
├── GOARCH : amd64
├── NumCPU : 6
├── GOPATH : /go
├── GOROOT : /usr/local/go
├── Compiler : gc
└── Date : Wednesday, 15 Jun 2022
API作成
下記ドキュメントに従ってAPI作成
$ bee api myapi
2022/06/15 00:11:13.922 [D] init global config instance failed. If you do not use this, just ignore it. open conf/app.conf: no such file or directory
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.4
2022/06/15 00:11:13 INFO ▶ 0001 Generate api project support go modules.
2022/06/15 00:11:13 INFO ▶ 0002 Creating API...
create /go/myapi/go.mod
create /go/myapi
create /go/myapi/conf
create /go/myapi/controllers
create /go/myapi/tests
create /go/myapi/conf/app.conf
create /go/myapi/models
create /go/myapi/routers/
create /go/myapi/controllers/object.go
create /go/myapi/controllers/user.go
create /go/myapi/tests/default_test.go
create /go/myapi/routers/router.go
create /go/myapi/models/object.go
create /go/myapi/models/user.go
create /go/myapi/main.go
2022/06/15 00:11:14 SUCCESS ▶ 0003 New API successfully created!
起動してみる
# ディレクトリ移動
$ cd myapi/
$ pwd
/go/myapi
# 起動
$ bee run
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.4
2022/06/15 00:15:07 WARN ▶ 0001 Running application outside of GOPATH
2022/06/15 00:15:07 INFO ▶ 0002 Using 'myapi' as 'appname'
2022/06/15 00:15:07 INFO ▶ 0003 Initializing watcher...
main.go:6:2: missing go.sum entry for module providing package github.com/beego/beego/v2/server/web (imported by myapi); to add:
go get myapi
2022/06/15 00:15:07 ERROR ▶ 0004 Failed to build the application: main.go:6:2: missing go.sum entry for module providing package github.com/beego/beego/v2/server/web (imported by myapi); to add:
go get myapi
go.sum
が存在しないと怒られた
エラー文見るとgo get myapi
コマンドを実行すると必要がありそうなので、プロセス中断してコマンド実行
# 指定コマンド実行
$ go get myapi
# go.sumが生成されていること確認
$ ls
conf go.mod main.go routers
controllers go.sum models tests
再度起動
$ bee run
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.4
2022/06/15 00:18:29 WARN ▶ 0001 Running application outside of GOPATH
2022/06/15 00:18:29 INFO ▶ 0002 Using 'myapi' as 'appname'
2022/06/15 00:18:29 INFO ▶ 0003 Initializing watcher...
# (実行結果中略)
2022/06/15 00:18:56 SUCCESS ▶ 0004 Built Successfully!
2022/06/15 00:18:56 INFO ▶ 0005 Restarting 'myapi'...
2022/06/15 00:18:56 SUCCESS ▶ 0006 './myapi' is running...
2022/06/15 00:19:00.944 [I] [parser.go:413] generate router from comments
2022/06/15 00:19:00.953 [I] [server.go:241] http server Running on http://:8080
良さそうなので、ブラウザで確認
ホスト側の18080
ポート開放しているのでそこで確認
良さそう
一応ログも確認
2022/06/15 00:21:11.733 [D] [router.go:955] | 172.25.0.1| 404 | 419.1µs| nomatch| GET /
404となっているので画面の表記と一致している
OK
少しコード覗いてみる
404画面は悲しいので200系統返ってこないか少し調査
まずはrouter見てみる
package routers
import (
"myapi/controllers"
beego "github.com/beego/beego/v2/server/web"
)
func init() {
ns := beego.NewNamespace("/v1",
beego.NSNamespace("/object",
beego.NSInclude(
&controllers.ObjectController{},
),
),
beego.NSNamespace("/user",
beego.NSInclude(
&controllers.UserController{},
),
),
)
beego.AddNamespace(ns)
}
おそらく /v1/object
や /v1/user
のエンドポイントが用意されてそう
今回は /v1/user
を深堀ってみる
routerからcontroller呼んでいるのでcontroller見てみる
package controllers
import (
"myapi/models"
"encoding/json"
beego "github.com/beego/beego/v2/server/web"
)
// Operations about Users
type UserController struct {
beego.Controller
}
// (略)
// @Title GetAll
// @Description get all Users
// @Success 200 {object} models.User
// @router / [get]
func (u *UserController) GetAll() {
users := models.GetAllUsers()
u.Data["json"] = users
u.ServeJSON()
}
// (略)
@router / [get]
とあるので、 /v1/user
にGETリクエスト投げれば models.User
が返されそう
modelも見てみる
package models
import (
"errors"
"strconv"
"time"
)
var (
UserList map[string]*User
)
func init() {
UserList = make(map[string]*User)
u := User{"user_11111", "astaxie", "11111", Profile{"male", 20, "Singapore", "astaxie@gmail.com"}}
UserList["user_11111"] = &u
}
type User struct {
Id string
Username string
Password string
Profile Profile
}
type Profile struct {
Gender string
Age int
Address string
Email string
}
// (略)
func GetAllUsers() map[string]*User {
return UserList
}
// (略)
GetAllUsers()
メソッド呼ぶと UserList
が返されそう
init()
部分で UserList
に初期値突っ込まれているので、その辺のデータが返されそう
ということで、 /v1/user
にGETリクエスト送ってみる
GETリクエスト試したいのでシンプルに http://localhost:18080/v1/user
にアクセスしてみる
下記内容が返されるので想定通り
ログ↓
2022/06/17 16:18:58.652 [D] [router.go:955] | 192.168.32.1| 200 | 231.6µs| match| GET /v1/user r:/v1/user/
gitignore設定
起動するたびに?コードに変更が入るたびに?内容変わってgit管理下に含めなくて良さそうなファイルをgitignoreに追加しておく
→api/myapi/lastupdate.tmp
やapi/myapi/myapi
を不要と判断したが、公式ドキュメント確認できていないため自己責任で
.env
api/pkg
# beego
api/bin/myapi
api/myapi/lastupdate.tmp
api/myapi/myapi
Swagger導入
Swaggerも使えるようなので下記ドキュメントを参考に使える状態に持っていく
何も下準備してないのでたぶん見れないが、/swagger
でSwaggerドキュメント確認できるっぽいのでとりあえずアクセス
しっかり404
2022/06/15 00:29:38.858 [D] [router.go:955] | 172.25.0.1| 404 | 1.6767ms| nomatch| GET /swagger/
ドキュメントを参考にコマンド実行してみる
bee run
コマンドのオプションで-downdoc=true
と-gendoc=true
をつければ良さそう
$ bee run -downdoc=true -gendoc=true
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.4
2022/06/15 00:33:49 WARN ▶ 0001 Running application outside of GOPATH
2022/06/15 00:33:49 INFO ▶ 0002 Using 'myapi' as 'appname'
2022/06/15 00:33:49 INFO ▶ 0003 Downloading 'https://codeload.github.com/beego/swagger/zip/refs/tags/v4.6.1' to 'swagger.zip'...
2022/06/15 00:33:51 SUCCESS ▶ 0004 3065067 bytes downloaded!
2022/06/15 00:33:51 INFO ▶ 0005 Unzipping 'swagger.zip'...
2022/06/15 00:33:52 SUCCESS ▶ 0006 Done! Deleting 'swagger.zip'...
2022/06/15 00:33:52 INFO ▶ 0007 Initializing watcher...
2022/06/15 00:33:58 INFO ▶ 0008 Generating the docs...
2022/06/15 00:34:03 SUCCESS ▶ 0009 Docs generated!
2022/06/15 00:34:10 SUCCESS ▶ 0010 Built Successfully!
2022/06/15 00:34:10 INFO ▶ 0011 Restarting 'myapi'...
2022/06/15 00:34:10 SUCCESS ▶ 0012 './myapi' is running...
2022/06/15 00:34:10.401 [I] [parser.go:85] /go/myapi/controllers no changed
2022/06/15 00:34:10.401 [I] [server.go:241] http server Running on http://:8080
確認してみる
2022/06/15 00:39:13.542 [D] [router.go:955] | 172.25.0.1| 200 | 5.6745ms| match| GET /swagger/
2022/06/15 00:39:13.562 [D] [router.go:955] | 172.25.0.1| 200 | 9.7623ms| match| GET /swagger/swagger-ui.css
2022/06/15 00:39:13.574 [D] [router.go:955] | 172.25.0.1| 200 | 15.9754ms| match| GET /swagger/swagger-ui-standalone-preset.js
2022/06/15 00:39:13.582 [D] [router.go:955] | 172.25.0.1| 200 | 25.6023ms| match| GET /swagger/swagger-ui-bundle.js
2022/06/15 00:39:13.795 [D] [router.go:955] | 172.25.0.1| 200 | 2.8292ms| match| GET /swagger/favicon-32x32.png
良さそう!
テスト確認
tests/default_test.go
ファイルが存在していたのでテスト実行してみる
go test -v ./...
# myapi/tests
tests/default_test.go:13:2: missing go.sum entry for module providing package github.com/smartystreets/goconvey/convey (imported by myapi/tests); to add:
go get -t myapi/tests
FAIL myapi/tests [setup failed]
? myapi [no test files]
? myapi/controllers [no test files]
? myapi/models [no test files]
? myapi/routers [no test files]
FAIL
失敗
どうやらgo get -t myapi/tests
コマンドを実行する必要がありそうなので実行
$ go get -t myapi/tests
再度テスト実行
go test -v ./...
? myapi [no test files]
? myapi/controllers [no test files]
? myapi/models [no test files]
? myapi/routers [no test files]
2022/06/15 00:56:20.122 [W] init global config instance failed. If you donot use this, just ignore it. open conf/app.conf: no such file or directory
=== RUN TestGet
2022/06/15 00:56:20.131 [I] [default_test.go:28] testing TestGet Code[%d]
%s 200 {
"hjkhsbnmn123": {
"ObjectId": "hjkhsbnmn123",
"Score": 100,
"PlayerName": "astaxie"
},
"mjjkxsxsaa23": {
"ObjectId": "mjjkxsxsaa23",
"Score": 101,
"PlayerName": "someone"
}
}
Subject: Test Station Endpoint
Status Code Should Be 200 ✔
The Result Should Not Be Empty ✔
2 total assertions
--- PASS: TestGet (0.00s)
PASS
ok myapi/tests 0.018s
OK