【メモ】OpenAPI Specification(OAS 3.0) Swagger



# はじめに
Swagger(Swagger Editor)を触る機会ができたので、OAS3.0について軽く調べたことをメモする。
最初、Swagger 2.0とOpenAPI 3.0の違いがわからず混乱した。
[Live Demo](https://editor.swagger.io/?_ga=2.122960712.259393361.1644584062-674950696.1644151430) では、Swagger2.0のサンプルコードが記載されている。

本記事の内容について、参考サイトは下記の通り。
[About Swagger Specification | Documentation | Swagger](https://swagger.io/docs/specification/about/)
[OpenAPI Specification](https://swagger.io/specification/)

# OpenAPIってなに？
**OpenAPI Specification(OAS)**は、REST APIのためのAPI記述形式。

- エンドポイント(/users)と各操作(GET,POSTなど)
- パラメーターと入出力
- 認証方法

YAMLかJSONで記述できる。

# Swaggerってなに？
OAS仕様に基づいたオープンソースツールで、REST APIの設計、構築、文書化、及び使用に役立つ。

# 基本構造

雰囲気はこんな感じ。

```yaml
openapi: 3.0.0
info:
  title: Sample API
  description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
  version: 0.1.9
servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in CommonMark or HTML.
      responses:
        '200':    # status code
          description: A JSON array of user names
          content:
            application/json:
              schema: 
                type: array
                items: 
                  type: string
```

## メタデータ

```yaml
openapi: 3.0.0
```

## Paths

APIの個々のエンドポイント（パス）と、対応するHTTPメソッドを定義できる。

下記の情報を含めることができる。

- パラメーター
- リクエストボディ
- レスポンスのステータスコード（200,400）
- レスポンスの中身（コンテンツ）

## Parameters

URLパス（`/users/{userId}`）、クエリ文字列（`/users?role=admin`）、ヘッダー（`X-CustomHeader: Value`）、またはCookie（`Cookie: debug=0`）を介してパラメーターを渡すことができる。

データ型、形式、必須などを定義できる。

## Request Body

`requestBody`キーワードを使用して本文のコンテンツとメディアタイプを記述できる。

## Responses

ステータスコードとレスポンスボディ(schema)を定義できる。
スキーマは、インラインで定義することも、`[$ref](https://swagger.io/docs/specification/using-ref/)`を介して参照することもできる。
HTTPステータスコードは、引用符で囲む必要あることに注意する。

```yaml
responses:
        '200':
          description: A user object.
```

## Input and Output Models

グローバル セクション`components/schemas`では、APIで使用される一般的なデータ構造を定義できる。
パラメータ、リクエストボディ、レスポンスボディなど必要なときに `$ref` で参照できる。

```yaml
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
          example: 4
        name:
          type: string
          example: Arthur Dent
      # Both properties are required
      required:  
        - id
        - name
```

レスポンスやリクエストボディで参照するとき。

```yaml
responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

〜〜〜

requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
```

## ***Authentication***

`securitySchemes`と`security`キーワードは、APIで使用される認証方法を説明するために使用される。

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

サポートされる認証法は以下の通り。

- HTTP認証
- APIキー（ヘッダー、クエリパラメータ、Cookie）
- [OAuth 2](https://swagger.io/docs/specification/authentication/oauth2/)
- [OpenID Connect Discovery](https://swagger.io/docs/specification/authentication/openid-connect-discovery/)

# Media Types

リクエストやレスポンスボディのデータ形式のこと。
JSON、XML、画像が一般的。

```yaml
paths:
  /employees:
    get:
      summary: Returns a list of employees.
      responses:
        '200':      # Response
          description: OK
          content:  # Response body
            application/json:  # Media type
              schema:          # Must-have
                type: object   # Data type
                properties: 
                  id:
                    type: integer
                  name:
                    type: string
                  fullTime: 
                    type: boolean
                example:       # Sample data
                    id: 1
                    name: Jessica Right
                    fullTime: true
```

## メディアタイプ名の一覧

```yaml
application/json
application/xml
application/x-www-form-urlencoded
multipart/form-data
text/plain; charset=utf-8
text/html
application/pdf
image/png
```

## componentsから参照

```yaml
content:  # Response body
            application/json:  # Media type
             schema: 
               $ref: '#/components/schemas/Employee'    # Reference to object definition
            application/xml:   # Media type
             schema: 
               $ref: '#/components/schemas/Employee'    # Reference to object definition
components:
  schemas:
    Employee:      # Object definition
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        fullTime: 
          type: boolean
```

# ***Paths and Operations***

OASのグローバルセクションで定義される。

```yaml
paths:
  /ping:
    ...
  /users:
    ...
  /users/{id}:
    ...
```

## パステンプレート

中括弧`{}`を使用して、URLの一部を[パスパラメータ](https://swagger.io/docs/specification/describing-parameters/#path-parameters)としてマークできる。

## ***Operations***

OAS3.0では、`get`, `post`, `put`, `patch`, `delete`, `head`, `options`,`trace` をサポートする。
1つのパスで複数の操作をサポートできる。
`tags`–リソースまたはその他の修飾子によって操作を論理的にグループ化するために使用される。

```yaml
paths:
  /users/{id}:
    get:
      tags:
        - Users
      summary: Gets a user by ID.
```

## パス内のクエリ文字列

パスにクエリ文字列パラメータを含めることができない。代わりに、[クエリパラメータ](https://swagger.io/docs/specification/describing-parameters/#query-parameters)として定義する必要がある。

```yaml
paths:
  /users:
    get:
      parameters:
        - in: query
          name: role
          schema:
            type: string
            enum: [user, poweruser, admin]
          required: true
```

## operrationId

操作を識別するために使用されるオプションの一意の文字列。

```yaml
/users:
  get:
    operationId: getUsers
    summary: Gets all users
    ...
  post:
    operationId: addUser
    summary: Adds a new user
    ...
/user/{id}:
  get:
    operationId: getUserById
    summary: Gets a user by user ID
    ...
```

# **[データモデル（スキーマ）](https://swagger.io/docs/specification/data-models/)**

今後、抑えたい。

# [Components Section](https://swagger.io/docs/specification/components/)

例。

```yaml
components:
  #-------------------------------
  # Reusable schemas (data models)
  #-------------------------------
  schemas:
    User:             # Can be referenced as '#/components/schemas/User'
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    Error:            # Can be referenced as '#/components/schemas/Error'
      type: object
      properties:
        code:
          type: integer
        message:
          type: string
  #-------------------------------
  # Reusable operation parameters
  #-------------------------------
  parameters:
    offsetParam:      # Can be referenced via '#/components/parameters/offsetParam'
      name: offset
      in: query
      description: Number of items to skip before returning the results.
      required: false
      schema:
        type: integer
        format: int32
        minimum: 0
        default: 0
    limitParam:       # Can be referenced as '#/components/parameters/limitParam'
      name: limit
      in: query
      description: Maximum number of items to return.
      required: false
      schema:
        type: integer
        format: int32
        minimum: 1
        maximum: 100
        default: 20
  #-------------------------------
  # Reusable responses
  #-------------------------------
  responses:
    404NotFound:       # Can be referenced as '#/components/responses/404NotFound'
      description: The specified resource was not found.
    ImageResponse:     # Can be referenced as '#/components/responses/ImageResponse'
      description: An image.
      content:
        image/*:
          schema:
            type: string
            format: binary
    GenericError:      # Can be referenced as '#/components/responses/GenericError'
      description: An error occurred.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
```

# おわりに

こっちの[ドキュメント](https://swagger.io/specification/) 読む前に、力尽きた。
OASの雰囲気は把握できたので、参考にしながらであれば記述できそう。
認証まわりは全く理解していないので、また今度調べたい。