Swaggerを使ってAPI仕様を共有する

# 要約

- swaggerの説明
- 使い方

# 背景

クライアントとサーバーの実装者が分かれていて情報共有に時間がかかる状況です。
事前にAPIの仕様だけは固めて共有しておきたいです。

ただ、手書きのドキュメントの場合は曖昧な表現が残り、誤解が生じる可能性があります。
ドキュメントのバリデーションができると嬉しいです。
欲を言えば、仕様の動作を確認するためのスタブサーバが作れると嬉しいです[^1]。

[^1]: サーバー側を担当しています。生成したクライアントの使い勝手はわかりません。

そこでswaggerを使います。

# swaggerとは？

[Swagger](https://swagger.io/)はWeb APIのドキュメンテーション仕様と、それを作る・使うツール群です。

## ドキュメンテーション仕様
最新のドキュメンテーション仕様は[OpenAPI 3.0](https://swagger.io/specification/)です。
ツール群の対応が終わっていません。
現時点では、前身の[Swagger 2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md)を使います。

## Swagger Editor

[Swagger Editor](https://swagger.io/swagger-editor/) はSwagger 2.0を編集するための、エディタです。
WYSIWYGでAPI仕様が書けます。

[オンラインエディタ](https://editor.swagger.io//#/)が提供されています。
どんなものかイメージを掴むのは、これを触ってみるのが良いでしょう。

オフラインで利用したい場合は、Dockerイメージも提供されています。

```sh
docker run --rm -d -p 80:8080 swaggerapi/swagger-editor
```

を実行すれば、 http://localhost で利用できます。

## Swagger Codegen

[Swagger Codegen](https://swagger.io/swagger-codegen/)は Swagger 2.0 から、各種言語のAPIクライアントまたはスタブサーバーを生成するツールです。

前述のSwagger Editorに組み込まれており、`Create Server`タブ、`Create Client`タブから生成できます。
生成されるコードが持つ機能は言語によってマチマチです。

例えば、現時点の最新バージョン 2.3.1 で生成した、Ruby on Rails 5のスタブサーバーは起動できません。
masterブランチでは修正されています（しました）。


### masterブランチ

masterブランチを利用するには、Github上で公開されているソースコードを使います。
Swagger CodegenはJava7以上でないと動かないことに注意してください。

必要であれば、`JAVA_HOME`を設定してください。

```
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
export PATH=${JAVA_HOME}/bin:$PATH
```

git clone 〜 依存パッケージの取得

```sh
git clone git@github.com:swagger-api/swagger-codegen.git
cd swagger-codegen
mvn clean package
```

ビルド

```sh
./mvnw clean package
```

実行

```sh
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i ~/swagger_test/swagger.yaml -l rails5 -o ~/swagger_test/rails5
```

Ruby on Rails 5のスタブサーバーを生成する例です。

### カスタマイズ

各言語の生成機能はモジュール化されています。
ソースコードは swagger-codegen/modules/swagger-codegen/src/main/ 配下にあります。
この中には

- java
- resources

の２つのディレクトリがあります。

#### テンプレート
主に変更するのは、resourcesディレクトリに入っているテンプレートです。
例えば、Rails５のコントローラーのテンプレートは[controller.mustache](
https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/main/resources/rails5/controller.mustache) です。

ファイル名の通り[mustache](https://mustache.github.io/)形式のテンプレートファイルです。

#### ソースコード

javaディレクトリには`CodegenConfig`を実装したクラスが入っています。

例えば [java/io/swagger/codegen/languages/Rails5ServerCodegen.java](https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/Rails5ServerCodegen.java)です。

##### プラグインのインターフェース CodegenConfig

プラグインは`CodegenConfig`型で扱われます。

[Codegen.java:L123](https://github.com/swagger-api/swagger-codegen/blob/4d4af7144656c80e8e63779191fd5a22fce65dc8/modules/swagger-codegen/src/main/java/io/swagger/codegen/Codegen.java#L123)

```java
public static List<CodegenConfig> getExtensions() {
    ServiceLoader<CodegenConfig> loader = ServiceLoader.load(CodegenConfig.class);
    List<CodegenConfig> output = new ArrayList<CodegenConfig>();
    for (CodegenConfig aLoader : loader) {
        output.add(aLoader);
    }
    return output;
}
```

ServiceLoaderは、Javaでプラグインを作るために仕組みです。
この仕組みを使って、引数で指定された言語に合わせて、生成するコードを切り替えています。

参考：[ServiceLoaderでプラグインの仕組みをさくっと作る。 - うなの日記](http://unageanu.hatenablog.com/entry/20090326/1238073098)

##### 実装クラス

実装クラスは`[言語名]ServerCodegen`です。
直接的は`DefaultCodegen`を継承します。

[Rails5ServerCodegen.java:L26](https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/Rails5ServerCodegen.java#L26)

```java
public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig
```

つまり、`Rails5ServerCodegen`で上書きされていればカスタマイズされた動作、されていなければ
`DefaultCodegen`の動作をします。


## Swagger2Markdown

[Swagger2Markdown](https://github.com/Swagger2Markup/swagger2markup)は Swagger 2.0 からMarkdown形式のAPI仕様書を生成します。

dockerイメージが提供されています。

```sh
docker run --rm -v (pwd):/opt swagger2markup/swagger2markup convert -i /opt/swagger.yaml -f /opt/swagger -c /opt/config.properties
```


# 参考
- [swagger 初めて触ってみた - Qiita](https://qiita.com/TsuyoshiUshio@github/items/50f8b7fe75663e63c968)
- [SwaggerでRESTful APIの管理を楽にする - Qiita](https://qiita.com/disc99/items/37228f5d687ad2969aa2)
- [Swagger Code Generator (swagger-codegen) の server stub の レスポンスが empty object になるのなんで？ - Qiita](https://qiita.com/kalibora/items/225daf474700561c983b)
- [Swaggerを使ってAPIの繋ぎ込みを楽にするための取り組み | GRIPHONE ENGINEER'S BLOG](https://tech.griphone.co.jp/2017/10/08/swagger/)