swagger 初めて触ってみた

Serverless や、DevOps 周りのコードを書いていると、そこここで、Swagger という言葉を耳にする。ふわっと雰囲気だけわかるけど、実際触ったことなかったのでちょっとだけ、触ってみた。

[Swagger](https://swagger.io/)は、OpenAPI の世界最大のAPI 開発ツールのフレームワークらしい。これがあると、APIのライフサイクルをまたいで、デザインからドキュメント、テストから開発まで面倒をみてくれるようだ。

# なぜ swagger に興味を持ったか？

[Azure SDK for Go](https://github.com/Azure/azure-sdk-for-go) のコードに貢献しようと思ってコードを読んでいるときに

> 今後このリポジトリは、swagger ベースの自動生成に移行する。C# の Azure SDK はすでにそれで成功している

と書いてあった。Azure はしょっちゅう機能強化されているのでなるほど。という感じだ。ちなみに、[Azure Rest API Specs](https://github.com/Azure/azure-rest-api-specs)参照のこと。

API のスペックがあると、ドキュメントから、ソースコード（クライアントとサーバー両方）を様々な言語で生成してくれる。ざっと、C# を見たら、ASP.NET や、ASP.NETCore まであった。これはきっと相当楽ちんだし、インターフェイスが共通化されるし、ドキュメントも生成されるし、いいことづくめじゃないか！

ともかく、コードを書いてなんか生成してみよう。

# OpenAPI(Swagger) Specification を作成する。

オンラインでも Swagger エディタが使える様子。実際つかってみると、問題があるときにいろいろ怒られるのでいい感じ。

<img width="1356" alt="swagger01.png" src="https://qiita-image-store.s3.amazonaws.com/0/3470/d33b8a0d-c573-5867-4fce-6aef5be4d2f6.png">

実際にスペックを書いてみると、仕様　[OpenAPI Specification](https://swagger.io/specification/#infoObject)を読みながら書いてもなかなかエラーが消えない。なんでやねん！文法どおりやんけ！とおもったら、ポイントは最初だった。

```
openapi: 3.0.0
```

が、

```
swagger: "2.0"
```

になっていた。どちらも間違いではないが、Swagger のページでは、普通にアクセスすると、3.0　のページがでる。世の中のサンプルは、`swagger: 2.0` が多いので、初めてだったので混乱してしまった。うまく出来てみると、図のように、プレビューで、API リファレンスが出来ていて見えるようになっている。いいね！ちなみに Visual Studio Code にも、プラグインがあった。

* {Swagger Viewer}(https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer)

これもすごくいい感じ。

<img width="1065" alt="swagger02.png" src="https://qiita-image-store.s3.amazonaws.com/0/3470/a860ec74-48b9-fd1e-16fd-47a8bf9a26f4.png">


# コードを生成する。

さて、コードを生成する方法は、`swagger-codegen-cli` を使えば一発らしい。Homebrewや、JAR ファイル、Docker 等が提供されている。私は、Windows なので、さてどれでやるものかと思ったが、Docker がうまくいかなかったので、JAR ファイルを選択してみた。 JAR ファイルを、Bash on Windows の方で動かしてみよう。

まず jar をダウンロード

```
wget http://central.maven.org/maven2/io/swagger/swagger-codegen-cli/2.2.3/swagger-codegen-cli-2.2.3.jar -O swagger-codegen-cli.jar
```

最初にめんどくさいので、`.bashrc` に、こんな雰囲気でエイリアスを書いておく。

```
alias swagger-codegen-cli='java -jar /home/ushio/Codes/swagger/swagger-codegen-cli-2.2.1.jar'
```

先ほどオンラインで作成した YAML ファイルを、`swagger.yml` という名前で保存して、実行する。うまくいかない。json のフォーマットにしたりして試してみるが、同じくうまくいかない。ファイルはちゃんとあるので、なんじゃそりゃ？という感じ。

```
$ swagger-codegen-cli generate -i swagger.json -l go
[main] INFO io.swagger.parser.Swagger20Parser - reading from swagger.json
[main] INFO io.swagger.parser.Swagger20Parser - reading from swagger.json
Exception in thread "main" java.lang.RuntimeException: missing swagger input or config!
        at io.swagger.codegen.DefaultGenerator.generate(DefaultGenerator.java:132)
        at io.swagger.codegen.cmd.Generate.run(Generate.java:223)
        at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:36)
```

試行錯誤してわかったのだが、少なくとも私の試したバージョンの(2.2.3) ではだめだった。どうすればよかったかというと、`swagger: 2.0` の方のAPI を使うと、ちゃんと生成された。多分次の 3.x で OpenAPI 3.0 対応になるのではと思われる。

## Go 

Client と、 Server の両方がしっかり生成されている。こりゃ楽だ！

<img width="1368" alt="swagger03.png" src="https://qiita-image-store.s3.amazonaws.com/0/3470/7df3def7-84f0-bce2-471b-31af638b684c.png">

## C# 

こちらもがっつり生成されている。テストのテンプレートまで！ただ、Visual Studio 2017 で開こうとしたらバージョンが古そうではあったが、しかし、これぐらい生成されると嬉しい。サーバーとクライアントの両方がある。

<img width="1368" alt="swagger04.png" src="https://qiita-image-store.s3.amazonaws.com/0/3470/174e226f-547f-7b8b-4e78-d87f2f550db0.png">

# まとめ

無事、swagger の specification を作って、ドキュメントを観察して、コードを生成するところまでは実験できた。[OpenAPI 3.0](https://swagger.io/docs/specification/authentication/api-keys/)の仕様だと、Authentication のところで、AccessToken にも対応しているようだ。対応言語もものすごく多い！

> API clients: ActionScript, Apex, Bash, C# (.net 2.0, 4.0 or later), C++ (cpprest, Qt5, Tizen), Clojure, Dart, Elixir, Eiffel, Go, Groovy, Haskell, Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx), Kotlin, Lua, Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations) Objective-C, Perl, PHP, PowerShell, Python, Ruby, Rust, Scala, Swift (2.x, 3.x, 4.x), Typescript (Angular1.x, Angular2.x, Fetch, jQuery, Node)
Server stubs: C# (ASP.NET Core, NancyFx), C++ (Pistache, Restbed), Erlang, Go, Haskell, Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework), PHP (Lumen, Slim, Silex, Symfony, Zend Expressive), Python (Flask), NodeJS, Ruby (Sinatra, Rails5), Scala (Finch, Scalatra)

[Get started with API Apps, ASP.NET, and Swagger in Azure App Service](https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-dotnet-get-started) こんなページも見つけた。確かにこれは、今後必須ですね！

## リソース

* [Swagger](https://swagger.io/)
* [Azure SDK for Go](https://github.com/Azure/azure-sdk-for-go)
* [Azure Rest API Specs](https://github.com/Azure/azure-rest-api-specs)
* [OpenAPI Specification](https://swagger.io/specification/#infoObject)
* [OpenAPI 3.0](https://swagger.io/docs/specification/authentication/api-keys/)
* [Swagger Code Generator](https://github.com/swagger-api/swagger-codegen#docker)
* [SwaggerでRESTful APIの管理を楽にする](http://qiita.com/disc99/items/37228f5d687ad2969aa2)