OpenAPIのレスポンス例定義をもとにSwagger Codegenでスタブサーバを生成する


本記事では、[Swagger Codegen](https://github.com/swagger-api/swagger-codegen)による **スタブサーバ** の生成と実行までの流れを説明します。なお、本記事ではあるエンドポイントへのリクエストに対して、意図したダミーデータを返すことができるAPIサーバのことをスタブサーバと呼びます。

[OpenAPI](https://github.com/OAI/OpenAPI-Specification)では、APIのレスポンス仕様定義でレスポンスとして返すデータの例を書くことができます。レスポンス定義における `examples` 配下へレスポンスデータの例を書いたものを次に示します。

```
'200':
  description: a pet to be returned
  schema:
    $ref: '#/definitions/Pet'
  examples:
    application/json:
      name: 'Fluffy'
      tag: 'cat'
      id: 1
```

`examples` 配下に書くExamples Objectの仕様は次のリンク先のとおりです。

- [OpenAPI-Specification/2.0.md at master · OAI/OpenAPI-Specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#exampleObject)

Swagger Codegenを使うとOpenAPIで書いたAPI仕様から、指定した言語で書かれたAPIサーバを生成することができます。また、Node.jsなどを指定して生成したサーバはOpenAPIで書いた `examples` 配下のデータをダミーデータとして返すことができます[^1]。

[^1]: Swagger Codegen v2.2.3現在、Rails 5として生成したサーバなどは `examples` を考慮せず、固定値しか返さないようです

スタブサーバを使うと、先にAPI仕様を決めてレスポンス例を書くことで、APIの完成を待たずしてフロントエンドの開発を進めることができるようになります。これは、APIとフロントエンドで分担して開発を進めるような場面で便利です。

今回はNode.jsで書かれたスタブサーバを生成しDockerコンテナ内で実行するところまでを説明します。

# OpenAPIによる仕様定義

まずはOpenAPIで仕様を定義します。今回は例として次の `swagger.yml` を書いておきます。`GET /v1/pets` だけが定義されている単純な仕様です。

```yaml:swagger.yml
swagger: '2.0'
info:
  version: 1.0.0
  title: Stub API
host: api.example.com
basePath: /v1
schemes:
  - https
consumes:
  - application/json
produces:
  - application/json
paths:
  /pets:
    get:
      description: find pets
      operationId: findPets
      responses:
        '200':
          description: pet response
          schema:
            type: array
            items:
              $ref: '#/definitions/Pet'
          examples:
            application/json:
              - name: 'Fluffy'
                tag: 'cat'
                id: 1
              - name: 'Lassie'
                tag: 'dog'
                id: 2
definitions:
  Pet:
    required:
      - id
      - name
    properties:
      id:
        type: integer
        format: int64
      name:
        type: string
      tag:
        type: string
```

# Swagger Codegenによるスタブサーバ生成

上述した `swagger.yml` からSwagger CodegenのCLIツールでスタブサーバを生成します。Swagger Codegenを実行するには本来はJavaの環境を準備する必要がありますが、今回はJavaの環境は準備せずにDocker経由で使います[^2]。

[^2]: 公式Dockerイメージが `latest` タグしかないようなので、この記事を書いた時点での最新版 (v2.2.3) を使っています

```
$ docker pull swaggerapi/swagger-codegen-cli
```

次のコマンドで、カレントディレクトリの `swagger.yml` からNode.jsで書かれたAPIサーバを生成します。

```
$ docker run --rm -v ${PWD}:/local swaggerapi/swagger-codegen-cli generate -l nodejs-server -i /local/swagger.yml -o /local/out
```

これで、カレントディレクトリ内の `out` ディレクトリ配下にスタブサーバが生成されています。

# スタブサーバの起動

今回はNode.jsのAPIサーバを生成したので、Node.jsのDockerイメージを利用した `Dockerfile` を `out` ディレクトリに置きます。

```Dockerfile
FROM node:latest

ENV APP_HOME /usr/src/app
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME

COPY api $APP_HOME/api
COPY controllers $APP_HOME/controllers
COPY index.js \
     package.json \
     $APP_HOME/

EXPOSE 8080
RUN npm install
```

`out` ディレクトリ内で次のコマンドを実行し、Dockerイメージを作ります。

```
$ docker build -t stub_server .
```


`out` ディレクトリ内で次のコマンドを実行すると、スタブサーバが起動し、localhostの8080番ポートでHTTPリクエストを受け付けるようになります。

```
$ docker run --rm -p 8080:8080 stub_server npm start
```

ためしにHTTPリクエストを発行してみると、OpenAPIで定義したレスポンス例が返ってくることがわかります。

```
$ curl http://localhost:8080/v1/pets | jq .
[
  {
    "name": "Fluffy",
    "tag": "cat",
    "id": 1
  },
  {
    "name": "Lassie",
    "tag": "dog",
    "id": 2
  }
]
```

以上の要領でAPI定義を先に決めて、スタブサーバを起動できるようにしておくと、API／フロントエンドの並行開発が効率化できるでしょう。