Swaggerについて調べてみた


API連携設計において、見やすく使いやすいものを使ってみようということになりました。
職場の先輩がSwaggerがいいらしいと教えてくれたので調べてみました。

自分用メモなので間違っているかも...
やってみた記録として優しい気持ちでご覧ください。

## Swaggerとは

`OpenAPI仕様`に基づいて構築された一連のオープンソースのフレームワークです。

`OpenAPI仕様`とは`RESTful API`を記述するための標準仕様であり、yamlやjsonで記述できます。

`RESTful API`とはWebシステムを外部から利用するためのプログラムの呼び出し規約(API)の種類の一つで、RESTと呼ばれる設計原則に従って策定されたものです。一般的にはRESTの考え方をWeb APIに適用したものをRESTful APIと呼んでいます。
URLやURIは同じでもHTTPメソッドが違うことによりアクションを変えることができます。

例えば以下のようなエンドポイントがあったとします。(railsの場合で記述します)

```
/books/{id}
```

上記のURIでHTTPメソッドがGETだった場合はshowアクションが働きます。
POSTならcreateアクション、PATCHならupdateアクション、DELETEならdestroyアクションです。
このようにURIは同じでもHTTPメソッドによってアクションが変わるのが`RESTful API`です。
(偉そうに言ってますがRESTfulについてはフワッとしか分からなかったので昨日先輩が分かりやすく教えてくれました:sunglasses:）


## ツール

- Swagger Codegen
OpenAPI仕様で定義されたAPIのスタブとクライアントSDKを生成します。
スタブとはRESTful APIのリクエストに対するレスポンスが期待通りの値を返してくれるかをテストするためのモジュールを指します。

- Swagger Editor
APIを設計、記述、文書化できるエディターです。
Swaggerはまずここからやるのが良さそう。

- Swagger UI
OpenAPI仕様で記述されたドキュメントをHTML形式で自動生成します。

- Swagger Spec
Swaggerの仕様に準じたドキュメントが確認できます。(全部英語)

Swagger ViwerというVSCodeの拡張機能もあるみたい。
Swaggerは機能が豊富すぎて慣れるの大変そうだが見やすい、お洒落、作る人によっての差がないなどすごく良さそうだなという印象。


## やってみた

Dockerでやるなど様々なやり方があるようですが、私はまず簡単に試せるwebへのアクセスを試してみました。[こちらへ](https://editor.swagger.io/)

アクセスすると以下のような画面になります。

![スクリーンショット 2021-04-02 10.41.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051152/3f560e4d-1394-311f-68c7-f32dfdc6a23f.png)


記述の仕方は以下の記事を参考にさせて頂きました。ありがとうございます！
[OpenAPI Specification チートシート](https://techblog.asahi-net.co.jp/entry/2019/03/04/102734)
[Swaggerの記法まとめ](https://qiita.com/rllllho/items/53a0023b32f4c0f8eabb)
[OpenAPI (Swagger) 超入門](https://qiita.com/teinen_qiita/items/e440ca7b1b52ec918f1b)

では詳しく見ていきます。文中に解説を書きます。
まずはタイトルなどの上部の部分です。

```yaml
#Swaggerのバージョン
swagger: "2.0"

#タイトルなど今回のドキュメントの説明をinfoに記述。
info:
  #ドキュメントの概要
  description: "これは○○○に関するAPIです"
  #APIバージョン
  version: "1.0.0"
  #ドキュメントのタイトル。画面右側の一番上に表示。
  title: "Swagger Petstore"
  #利用規約
  termsOfService: "http://swagger.io/terms/"
  #APIの問い合わせ先
  contact:
    email: "apiteam@swagger.io"
  #APIのライセンス
  license:
    name: "Apache 2.0"
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"

#画面右側のpetと書いてある部分。APIで利用するタグの一覧。
tags:
#tagの名前
- name: "pet"
  #tagの説明
  description: "Everything about your Pets"
  #外部のドキュメント
  externalDocs:
    description: "Find out more"
    url: "http://swagger.io"
- name: "store"
  description: "Access to Petstore orders"
- name: "user"
  description: "Operations about user"
  externalDocs:
    description: "Find out more about our store"
    url: "http://swagger.io"
```

次にpathの部分を見ていきます。
pathに定義する情報をもとにエントリポイントが作成されるため`paths`はとても重要です。

```yaml
paths:
  #定義したいエントリポイントのパス。
  /pet:
    #HTTPメソッド
    post:
      #どのtagsか。
      tags:
      - "pet"
      #エンドポイントの概要。サマリ。
      summary: "Add a new pet to the store"
      #エンドポイントの説明。
      description: ""
      #	MIME Typeを記述。
      consumes:
      - "application/json"
      - "application/xml"
      produces:
      - "application/xml"
      - "application/json"
      #リクエストで渡すパラメーター
      parameters:
        #パラメーターの場所。query, header, path, formData, bodyの5種類のどれかを記述。
      - in: "body"
        #パラメーターの名前
        name: "body"
        #パラメーターの説明
        description: "Pet object that needs to be added to the store"
        #必須パラメーターかどうかをtrueかfalseで記述
        required: true
        schema:
          $ref: "#/definitions/Pet"
      #返ってくるレスポンス
      responses:
        "405":
          description: "Invalid input"
      #適用するセキュリティ
      security:
      - petstore_auth:
        - "write:pets"
        - "read:pets"
```

上記の`parameters`の`in`が`body`以外の場合は以下のように`type`や`format`を使います。

```yaml
parameters:
      - name: "petId"
        in: "path"
        description: "ID of pet to return"
        required: true
        #パラメーターのタイプ。
        type: "integer"
        #パラメーターの型。
        format: "int64"
```

`type`と`format`の型に関しては[こちらの公式のドキュメント](https://swagger.io/specification/#dataTypeFormat)に記載がありました。




## HTMLとして出力

yamlファイルを生成し、その後HTMLに変換しかっこいい感じにしたかったのでこちらも先輩に教えて頂いたredocというツールを使ってみます。
[redocGithub](https://github.com/Redocly/redoc)

私のやり方です。

①SwaggerをyamlもしくはJSON形式でファイルをダウンロードする。
![スクリーンショット 2021-04-02 12.57.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051152/50809acc-a4f4-9338-64a9-7ceeadea4c9f.png)

②Swaggerというフォルダを作成し、そこに先ほどダウンロードしたファイルを移動する。

③同じSwaggerフォルダに`index.html`というファイルを作成する。

④Swaggerディレクトリにいる状態で以下のコマンドを実行する。
npmでインストールするのでnode.jsとnpmがインストールされていることが前提。

```ターミナル
npm install -g redoc-cli
```

⑤成功したらそのまま以下のコマンドを実行する。
(`swagger.json`のところにはダウンロードしたファイル名を、
`index.html`のところには出力したいファイル名をご自身の環境に合わせて変更してください。)

```ターミナル
redoc-cli bundle swagger.json -o index.html
```

⑥index.htmlファイルをブラウザで開く。


これだけで、めっちゃ見やすくてかっこ良く出力できました！
この方法であれば、htmlファイルを渡すだけで環境に関わらず見ることができるのかなと思います！