🐈

PrismでOpenAPIを利用したモックサーバーを作る

2022/04/24に公開約7,700字

背景

OpenAPIに記述した内容でモックサーバーを手軽に作れそうなPrismを試しに使ってみました.

https://meta.stoplight.io/docs/prism/ZG9jOjky-installation

OpenAPIを作る

まずはOpenAPIを作る必要があります.
色々試したかったのでAPIとしてはちょっと変な部分もありますが,今回は次のようなものを作成しました.

openapi.yml
openapi: 3.0.0
info:
  title: Prism Test API
  version: '1.0'
servers:
  - url: 'http://localhost:4010'
paths:
  /users:
    get:
      summary: ユーザー一覧取得API
      tags:
        - users
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/res_get_users'
      operationId: get-users
      description: ユーザー一覧を取得する
    post:
      summary: ユーザー作成API
      operationId: post-users
      responses:
        '200':
          description: OK
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/res_status_code_other_200'
      description: ユーザーを作成する
      tags:
        - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/req_post_users'
        description: リクエストボディ
      parameters:
        - schema:
            type: string
          in: header
          name: X-Api-Key
          description: APIキー
          required: true
  '/users/{id}':
    parameters:
      - schema:
          type: integer
        name: id
        in: path
        required: true
        description: ユーザーID
    get:
      summary: ユーザー詳細取得API
      tags:
        - users
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/res_get_users_id'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/res_status_code_other_200'
      operationId: 'get-users-:id'
      description: ユーザ詳細を取得する
components:
  schemas:
    res_get_users:
      title: res_get_users
      x-tags:
        - users
      description: GET /usersのレスポンスモデル
      type: object
      x-examples: {}
      properties:
        list:
          type: array
          items:
            type: object
            properties:
              id:
                description: ユーザーID
                type: integer
              name:
                type: string
                description: ユーザー名
            required:
              - id
              - name
      required:
        - list
    res_get_users_id:
      title: res_get_users_id
      type: object
      description: 'GET /users/{id}のレスポンスモデル'
      x-tags:
        - users
      properties:
        name:
          type: string
          description: ユーザー名
        nickname:
          type: string
          description: ニックネーム
        isAvailable:
          type: boolean
          description: 利用可能か
      required:
        - name
        - nickname
        - isAvailable
      x-examples: {}
    res_status_code_other_200:
      title: res_status_code_other_200
      type: object
      description: ステータスコード200以外の場合のレスポンスモデル
      properties:
        message:
          type: string
          description: エラーメッセージ
        code:
          type: integer
          description: エラーコード
      required:
        - message
        - code
      x-tags:
        - status-code
    req_post_users:
      title: req_post_users
      type: object
      description: POST /usersのリクエストモデル
      x-tags:
        - users
      properties:
        name:
          type: string
          description: ユーザー名
        nickname:
          type: string
          description: ニックネーム
        likeFood:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
                description: 好きな食べ物名
        year:
          type: integer
          description: 年齢
      required:
        - name
        - nickname
        - year

https://editor.swagger.io/ で表示してみるとこんな感じです.

Prismを起動する

起動の方法はnpmまたはyarnを使う方法とDockerを使う方法があり,今回はDockerを使いました.
公式ではファイル名がfile.yamlですが,上記で作成したopenapi.ymlに変えて実行します.

$ docker run --init --rm -v $(pwd):/tmp -p 4010:4010 stoplight/prism:4 mock -h 0.0.0.0 "/tmp/openapi.yml"

curlでモックサーバーにリクエストを投げてみる

GET /users

正常系

$ curl -X GET 'http://localhost:4010/users'
{"list":[{"id":0,"name":"string"}]}

POST /users

正常系(レスポンスなしで正しいか確認しずらいので,-iオプションをつけてステータスコード200が返ってくるかを確認)

$ curl -i -X POST 'http://localhost:4010/users' \
                            -H 'X-Api-Key: 1' \
                            -H 'Content-Type: application/json' \
                            -d '{
                        "name": "string",
                        "nickname": "string",
                        "likeFood": [
                          {
                            "name": "string"
                          }
                        ],
                        "year": 0
                      }'
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
Date: Sun, 24 Apr 2022 10:12:34 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 0		      

ステータスコード400(ステータスコードを変える場合は-H 'Prefer: code=400'のようにヘッダーに指定します.)

$ curl -i -X POST 'http://localhost:4010/users' \
                            -H 'X-Api-Key: 1' \
                            -H 'Content-Type: application/json' \
                            -H 'Prefer: code=400' \
                            -d '{
                        "name": "string",
                        "nickname": "string",
                        "likeFood": [
                          {
                            "name": "string"
                          }
                        ],
                        "year": 0
                      }'
HTTP/1.1 400 Bad Request
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
Content-type: application/json
Content-Length: 29
Date: Sun, 24 Apr 2022 10:42:30 GMT
Connection: keep-alive
Keep-Alive: timeout=5

{"message":"string","code":0}

GET /users/{id}

正常系

$ curl -X GET 'http://localhost:4010/users/1'
{"name":"string","nickname":"string","isAvailable":true}

パスパラメータをinteger以外にしたとき

$ curl -X GET 'http://localhost:4010/users/string'
{"type":"https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY","title":"Invalid request","status":422,"detail":"Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.","validation":[{"location":["path","id"],"severity":"Error","code":"type","message":"must be integer"}]}

ステータスコード500

$ curl -i -X GET 'http://localhost:4010/users/1' -H 'Prefer: code=500'
HTTP/1.1 500 Internal Server Error
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: *
Content-type: application/json
Content-Length: 29
Date: Sun, 24 Apr 2022 10:44:23 GMT
Connection: keep-alive
Keep-Alive: timeout=5

{"message":"string","code":0}

まとめ

自分で確認していませんが,exampleを記述しておくと,レスポンスのデータを変更できるようです.

https://zenn.dev/wim/articles/prism_mock_server_from_swagger

手軽にモックサーバーが立てることができました.
今回はざっと使っただけでしたがPrismのドキュメントも充実しており,他にも様々な用途がありそうです.

Discussion

ログインするとコメントできます