OpenAPIに入門する

# はじめに
こんにちは、最近機械学習系の記事を投稿したり、Web開発系の記事を投稿したりキャラが定まらない私ですが、今回は後者のWeb開発関連の記事です。

最近インターン活動の中で、**APIを記述および文書化するためのオープンソース形式であるApenAPI**をいうものを初めて触りました。
とても便利で、今後のプロダクト開発で知っていると何かと楽かなと思ったので、勉強してみることにしました。

この記事は、実際にチュートリアルを進めながら、仕様や使い方について学んだことを記録し、備忘録として個人的に活用することを目的にしています。

https://support.smartbear.com/swaggerhub/docs/en/get-started/openapi-3-0-tutorial.html


# 前提

チュートリアルを進める上での前提知識として、
- RESTful API に関する基本的な知識。
- YAML の基礎知識

の2つがあることが推奨されています。


## OpennAPIって何？

- OpenAPI仕様（元々はSwagger仕様として知られていた）の主な目的は、APIがどのように機能するかについての包括的なドキュメンテーションを提供することです。

- また、提供するドキュメンテーションは人間だけでなくマシン可読でもあります。つまり、このドキュメンテーションを解析し、**APIクライアントのコードを自動生成**したり、APIの返答を模倣するモックサーバーを立ち上げたりすることが可能です。その他にも、APIの仕様を試したり、評価したり、共有や検証を行ったりするツールが存在します。（便利♪）

- APIの仕様はYAMLファイルやJSONフォーマットで体系的に表現されます。


## Swaggerって何？

Swaggerは、APIの設計、開発、テスト、および文書化を簡単にするための一連のツールと仕様を指します。具体的には、Swaggerには以下のような要素があります。

| 項目              | 説明                                                                                                                                      |
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| **Swagger Specification (OpenAPI Specification)** | RESTful APIを定義するための標準フォーマット。APIのエンドポイントやリクエスト・レスポンス形式を詳細に記述。                            |
| **Swagger UI**    | Swagger/OpenAPI Specificationに基づいたインタラクティブなAPIドキュメントを生成。ブラウザ上でAPIの動作を試せる。                         |
| **Swagger Editor**| ウェブベースのエディタ。Swagger/OpenAPI Specificationを作成・編集し、リアルタイムでプレビュー可能。                                          |
| **Swagger Codegen**| Swagger/OpenAPI Specificationに基づいてクライアントSDKやサーバースタブを自動生成。様々な言語でのAPI実装を迅速に行える。                    |
| **Swagger Hub**   | APIの設計と文書化をクラウドベースで管理。チームでAPIを共同設計・管理でき、バージョン管理やアクセス制限も可能。                               |


両者の違いやSwaggerの使い方の簡単な説明は下記の記事にとてもわかりやすくまとまっていました。
こちらの記事でも触れていきますが、参考までに...

https://zenn.dev/chida/articles/25f4016560f6bf


## APIを作成する

### example (レコード会社のアーティスト情報を管理するためのAPI)

OpenAPI Specification（OAS）を使ったAPI定義は、APIを設計する際に非常に役立つツールです。[チュートリアル](https://support.smartbear.com/swaggerhub/docs/en/get-started/openapi-3-0-tutorial.html)では、レコードレーベルのアーティストデータベースに対するAPIを設計するプロセスを例にこのツールの使い方を解説しています。

OpenAPI Specificationを利用したAPIの定義は大きく3つのセクションに分けることができます。


- **Meta information**: APIのバージョン、タイトル、説明、サーバーURLなどの基本情報
- **Path items (endpoints)**: APIのエンドポイントを定義し、リソースに対する操作を指定
    - Parameters: クエリパラメータやパスパラメータを指定
    - Request bodies: POST、PUT、PATCHメソッドで送信されるデータの形式や内容を定義
    - Responses: 各エンドポイントのレスポンスコードとその内容を記述
- **Reusable components**: API全体で再利用可能なコンポーネントを定義
  - Schemas (data models): 再利用可能なデータモデルを定義
  - Parameters: 再利用可能なパラメータを定義
  - Responses: 再利用可能なレスポンスを定義
  - Other components: その他の再利用可能なコンポーネントを定義


####  1. メタ情報 (Meta Information)

APIの基本情報を定義します。このセクションには、APIのバージョン、タイトル、説明、サーバーのURL、および認証に関する情報が含まれます。

```yaml
openapi: 3.0.0
info:
  version: 1.0.0
  title: Simple Artist API
  description: A simple API to illustrate OpenAPI concepts

servers:
  - url: https://example.io/v1

components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
security:
  - BasicAuth: []
```

##### 解説:
- **openapi**: 使用するOpenAPIのバージョン（ここでは3.0.0）
- **info**: APIのバージョン、タイトル、説明
- **servers**: APIのエンドポイントがホストされるサーバーのURL
- **components**: 認証方法などの再利用可能なコンポーネントを定義します。ここではBasic認証を使用しています
- **security**: APIがどの認証スキームを使うかを指定します

#### 2. パス項目 (Path Items)

APIが提供するエンドポイント（パス）を定義します。各エンドポイントは、特定のリソースに対する操作を表します。ここでは、アーティストのリストを取得するGETメソッドと、新しいアーティストを追加するPOSTメソッドを定義します。

#### 2.1. GET /artists: アーティストリストの取得

```yaml
paths:
  /artists:
    get:
      description: Returns a list of artists 
      parameters:
        - name: limit
          in: query
          description: Limits the number of items on a page
          schema:
            type: integer
        - name: offset
          in: query
          description: Specifies the page number of the artists to be displayed
          schema:
            type: integer
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Artist'
        '400':
          $ref: '#/components/responses/400Error'
```

##### 解説:
- **/artists**: アーティストのリストにアクセスするエンドポイント。
- **parameters**: クエリパラメータ（limit、offset）を定義。これにより、取得するデータの範囲を指定可能。
- **responses**: 成功時（200）のレスポンスと、エラーレスポンス（400）を定義
- **$ref**: 再利用可能なコンポーネントへの参照


<details><summary> [$ref] について（可読性が上がるよ）</summary>

`$ref` を使わずに同じ内容を記述すると、以下のようになります。

```yaml
paths:
  /artists:
    get:
      description: Returns a list of artists 
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    artist_name:
                      type: string
                    artist_genre:
                      type: string
                    albums_recorded:
                      type: integer
                    username:
                      type: string
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
```

この場合、200 レスポンスのスキーマや 400 レスポンスのエラーメッセージの構造をすべて手動で記述する必要があります。

</details>


#### 2.2. POST /artists: アーティストの追加

```yaml
paths:
  /artists:
    post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Artist'
      responses:
        '200':
          description: Successfully created a new artist
        '400':
          $ref: '#/components/responses/400Error'
```

##### 解説:
- **post**: 新しいアーティストを追加するためのエンドポイント。
- **requestBody**: リクエストボディの内容を定義。アーティストの情報を含むJSONデータを受け取る。
- **responses**: 成功時（200）のレスポンスと、エラーレスポンス（400）を定義。

#### 2.3. GET /artists/{username}: 特定のアーティスト情報の取得

```yaml
paths:
  /artists/{username}:
    get:
      description: Obtain information about an artist from his or her unique username
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successfully returned an artist
          content:
            application/json:
              schema:
                type: object
                properties:
                  artist_name:
                    type: string
                  artist_genre:
                    type: string
                  albums_recorded:
                    type: integer
        '400':
          $ref: '#/components/responses/400Error'
```

##### 解説:
- **/{username}**: パスパラメータとしてアーティストのユーザー名を受け取るエンドポイント。
- **parameters**: パスパラメータの「username」を定義。必須項目としてマークされている。
- **responses**: 成功時（200）のレスポンスと、エラーレスポンス（400）を定義。

#### 3. 再利用可能なコンポーネント (Reusable Components)

複数のエンドポイントで使い回せるスキーマやレスポンス、パラメータを定義します。これにより、コードの重複を減らし、管理を容易にします。

```yaml
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic

  schemas:
    Artist:
      type: object
      required:
        - username
      properties:
        artist_name:
          type: string
        artist_genre:
          type: string
        albums_recorded:
          type: integer
        username:
          type: string

  parameters:
    PageLimit:
      name: limit
      in: query
      description: Limits the number of items on a page
      schema:
        type: integer

    PageOffset:
      name: offset
      in: query
      description: Specifies the page number of the artists to be displayed
      schema:
        type: integer

  responses:
    400Error:
      description: Invalid request
      content:
        application/json:
          schema:
            type: object 
            properties:
              message:
                type: string
```

##### 解説:
- **schemas**: データモデルを定義します。ここではアーティストの情報を保持する`Artist`スキーマを定義。
- **parameters**: クエリパラメータなど、複数のエンドポイントで使うパラメータを定義。
- **responses**: 標準的なエラーレスポンスなど、再利用可能なレスポンスを定義。


## 次のステップ

以上で、アーティストの情報を公開するRESTful APIを設計することに成功しました。
以降のステップとしては、

- 検証ツール（Swagger Editor / OpenAPI Generator）を利用して、構文/論理エラーを発見する
- ドキュメントを生成する（Swagger UIやReDocを使用）
- APIのモックサーバーの作成 (OpenAPI Specificationに基づいてモックサーバーを立ち上げ、実際のバックエンドが完成する前にAPIの動作を確認したり、クライアントの開発を進めたりする)
- **サーバーコードの自動生成**　： OpenAPI GeneratorやSwagger Codegenを使用して、APIのサーバースタブやクライアントSDKを自動生成する。

等あるようです。個人的には、一番下のコードの自動生成についてとても魅力（楽したい）を感じているため、次回の記事では、実際にコードを生成する手順について調査し、その内容をまとめていきたいと思っています！