Prismでモックサーバーを構築する

n-ozawan

皆さん、こんにちは。技術開発グループのn-ozawanです。
今年も日本人がイグノーベル賞を受賞しましたね。これで18年連続の受賞となりました。

本題です。
フロントエンドを新規開発しているときに、フロンドエンドから呼び出すAPIが開発済みであることは、ほとんどありません。APIをモック動作させることが出来れば、フロントエンドの開発は捗ることでしょう。今回は、OpenAPIで作成したAPI仕様書を元に使ってモックサーバーを構築できる、Prismについてお話しします。

Prism

概要

PrismはStoplightが提供する、OpenAPIで記述されたAPI仕様書を元に動作するモックサーバーです。node.jsの環境があれば、以下のコマンドでインストールすることが出来ます。

npm i -D @stoplight/prism-cli

今回は以下のAPI仕様を元に、Prismの動きを見ていきたいと思います。

openapi: 3.1.0

info:
  title: OpenAPI 仕様書 サンプル
  version: 0.0.1
  description: OpenAPIで記述したAPI仕様書のサンプルです。

paths:
  /api/user/{userId}:
    get: 
      operationId: getUserInfo
      summary: ユーザー情報取得
      description: ユーザー情報を取得する
      parameters: 
        - name: userId
          in: path
          description: ユーザーID
          required: true
          schema: 
            type: integer
      responses: 
        '200': 
          description: 成功
          content: 
            application/json: 
              schema: 
                type: object
                properties: 
                  userId:
                    description: ユーザーID
                    type: integer
                  name:
                    description: ユーザー名
                    type: string
                  age:
                    description: 年齢
                    type: integer
            '400':
          description: Bad Request.
        '404':
          description: Not Found.

Prism Mock を動かしてみる。

Prism Mockを起動してみましょう。以下のコマンドでPrismサーバーを起動します。

npx prism mock ./openapi.yaml

(省略)
[1:23:20 PM] › [CLI] ▶  start     Prism is listening on http://127.0.0.1:4010

以下のコマンドで動作を確認してみましょう。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"userId":0,"name":"string","age":0}

200応答がありましたね!

返却値を指定したい

レスポンスがあったのは良いのですが、なんだか内容が味気ないですね。返却値をそれっぽく見せたい場合は、schemaと同じレベルにexamplesを定義することで、返却する内容を変えることが出来ます。

schema: 
  (省略)
examples:
  tarou: 
    summary: 太郎の情報
    value:
      userId: 1
      name: 太郎
      age: 20
curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"userId":1,"name":"太郎","age":20}

太郎の情報が返ってきましたね!

返却値を動的に変えたい

いちいちexamplesを定義するのが面倒なので、なんでもいいから適当な値を入れたいケースもあるかもしれません。Prismには動的に値を設定してくれる機能があります。-dを付与してPrismサーバーを起動します。

npx prism mock ./openapi.yaml -d

もう一回リクエストを送信してみましょう。

curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"age":33300731,"name":"mollit consectetur aliquip dolor","userId":14850756}

値が設定されましたね。ただ、年齢の値がすごいことになっています。この場合、openapi.yamlの年齢のところに、minimummaximumを指定することである程度制御することが可能です。

age:
  description: 年齢
  type: integer
  minimum: 0
  maximum: 120
curl -i http://localhost:4010/api/user/1

HTTP/1.1 200 OK
(省略)
{"age":74,"name":"Ut","userId":55789416}

ただし、-dを付与した場合の注意点としては以下があり、実際に開発に使うのは難しそうです。

  • 一部の項目だけを動的に変えることは出来ない
    →全ての項目が動的に変わってしまう。
  • examplesの定義は無視される。
    →このAPIはexamplesの内容を返却して、別のAPIは動的に変える、などと言ったことが出来ない。
  • APIを呼び出すたびに返却される値が変わる
    →常に同じ値を返して欲しい、ということが出来ない。

呼び出したAPIの内容をチェックしたい

PrismはAPI仕様書と異なるリクエストを受けた場合、エラー応答をしてくれます。

curl -i http://localhost:4010/api/user/hoge

HTTP/1.1 400 Bad Request

上記のURLで{userId}の個所にhogeを指定しています。API仕様書ではURLの{userId}にはtype: integerを指定しているため、Prismは不正なリクエストであると判断して400エラーを返却します。もし間違ったAPI呼び出しを実装しても、早期に気付くことが出来ます。

なお、Prismは、API仕様に400が記載されているため、400で応答してくれました。もし、API仕様に400が無い場合は422で応答します。

responses:
  '200':
    (省略)
  '400':
    description: Bad Request.

レスポンスの内容を出し分けたい

例えば{userId}1を指定した場合は太郎の情報を、{userId}2を指定した場合は次郎の情報を返却したい、などのように、リクエストの内容によってレスポンスを変えたい場合もあります。しかし、残念なことにPrismはそのような動きに対応していません。代わりに以下のようなことは可能です。

まず、examplesに次郎の情報を追加します。

schema: 
  (省略)
examples: 
  tarou: 
    value:
      userId: 1
      name: 太郎
      age: 20
  jirou: 
    value:
      userId: 2
      name: 次郎
      age: 18

HTTPヘッダのPreferexample=jirouのように指定することで、該当する情報が返却されます。

curl -i http://localhost:4010/api/user/1 -H "Prefer:example=jirou"

HTTP/1.1 200 OK
(省略)
{"userId":2,"name":"次郎","age":18}

APIのモックサーバーは、言ってしまえばAPIが開発されるまでの繋ぎです。あとはテスト用でしょうか。その為にHTTPヘッダにPreferを実装をするのは避けたいところです。

画像ファイルなどのバイナリを返却したい

出来ません。残念ながらPrismは画像ファイルなどのバイナリに対応していません。

おわりに

「APIが開発されるまでの繋ぎ」と割り切れば、Prismはそこそこ使えるのではないでしょうか。ただ、個人的にはリクエストの内容によってレスポンスを変えられなかったり、画像ファイルなどのバイナリに対応していないなど、痒いところに手が届かないのが気になります。これらに対応するのであれば、Prismの前にサーバーを置いて別途対応するなどが考えられますが、そうなると手軽さから遠ざかりますね。

ではまた。

Recommendおすすめブログ