## [[oapi-codegen]]のインストール
```console
go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest
```
## [[OpenAPI Specification]]の[[YAML]]作成
[[Reqres]]を使う。
<div class="link-card">
<div class="link-card-header">
<span class="link-card-site-name">reqres.in</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<div>
<p class="link-card-title">
Reqres - A hosted REST-API ready to respond to your AJAX requests
</p>
</div>
<div class="link-card-description">
A hosted REST-API ready to respond to your AJAX requests
</div>
</div>
</div>
<a href="https://reqres.in/"></a>
</div>
サイト内に[[Swagger]]へのリンクもあって素晴らしい!
<div class="link-card">
<div class="link-card-header">
<img src="https://reqres.in/api-docs/favicon-32x32.png" class="link-card-site-icon"/>
<span class="link-card-site-name">reqres.in</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<div>
<p class="link-card-title">Swagger UI</p>
</div>
<div class="link-card-description">
</div>
</div>
</div>
<a href="https://reqres.in/api-docs/"></a>
</div>
> [!question] どうしてREADMEのエンドポイントを使わないのか?
>
> READMEにも記載されていた[[OpenAPI Specification]]のリポジトリにあるサンプルはエンドポイントにアクセスできなかった...
今回利用する`/users`の部分だけ抽出して `openapi.yaml`として作成。
```yaml
openapi: 3.0.0
info:
title: ReqRes API
description: Fake data CRUD API
version: "1"
servers:
- url: https://reqres.in/api
components:
schemas:
User:
type: object
properties:
id:
type: integer
email:
type: string
first_name:
type: string
last_name:
type: string
avatar:
type: string
paths:
/users:
get:
summary: Fetches a user list
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: per_page
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
page:
type: integer
per_page:
type: integer
total:
type: integer
total_pages:
type: integer
data:
type: array
items:
$ref: '#/components/schemas/User'
```
## コードを生成
[[パッケージ (Go)|パッケージ]]は`api`なので、`api`ディレクトリを作成し、配下に配置する。
```console
mkdir api
oapi-codegen -package api openapi.yaml > api/openapi.gen.go
```
`api/openapi.gen.go`にはimportエラーが含まれるので
```console
go mod tidy
```
## 自動生成されたコードを使って実装
以下のようなコードになる。
```go
package main
import (
"context"
"go-study/api"
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.GET("/", hello)
e.GET("/users", users)
e.Logger.Fatal(e.Start(":1323"))
}
func hello(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}
// 今回重要なのはココ!
func users(c echo.Context) error {
client, err := api.NewClientWithResponses("https://reqres.in/api")
if err != nil {
return err
}
res, err := client.GetUsersWithResponse(context.TODO(), nil)
if err != nil {
return err
}
return c.JSON(http.StatusOK, res.JSON200)
}
```
> [!caution]
> `NewClient`の方はレスポンスが不要な場合に使うケース。レスポンスが必要な場合は`NewClientWithResponses`を使う必要がある。
## 動作確認
サーバーを起動する。
```console
go run .
```
http://localhost:1323/users にアクセスして結果が返却されればOK。
```console
$ curl http://localhost:1323/users
{"data":[{"avatar":"https://reqres.in/img/faces/1-image.jpg","email":"
[email protected]","first_name":"George","id":1,"last_name":"Bluth"},{"avatar":"https://reqres.in/img/faces/2-image.jpg","email":"
[email protected]","first_name":"Janet","id":2,"last_name":"Weaver"},{"avatar":"https://reqres.in/img/faces/3-image.jpg","email":"
[email protected]","first_name":"Emma","id":3,"last_name":"Wong"},{"avatar":"https://reqres.in/img/faces/4-image.jpg","email":"
[email protected]","first_name":"Eve","id":4,"last_name":"Holt"},{"avatar":"https://reqres.in/img/faces/5-image.jpg","email":"
[email protected]","first_name":"Charles","id":5,"last_name":"Morris"},{"avatar":"https://reqres.in/img/faces/6-image.jpg","email":"
[email protected]","first_name":"Tracey","id":6,"last_name":"Ramos"}],"page":1,"per_page":6,"total":12,"total_pages":2}
```