stoplight.io prism
Stoplight 社の提供する製品やオープンソースのうち、 Prism について詳細を記録する
Mock
mock と proxy あるうちの mock 側。
base path の考え方
- そもそも spec でベースパスを指定するには
servers[].url
に'http://example.com/v1/base'
と指定し、そこから枝分かれするものはpaths
に'/cats/{catName}'
'/dogs/{dogName}'
などと記述する - この spec で prism を起動すると
/v1/base
という部分は失われ、http://0.0.0.0/cats/{catName}
http://0.0.0.0/dog/ {dogName}
などが有効なパスになるので要注意。 paths
にフルパスを指定するようにすれば、回避可能。 ('/v1/base/cats/{catName}'
'/v1/base/dogs/{dogName}'
)
Prefer
ヘッダでレスポンスを操る
色々便利よ
1. status code を操作
以下のようにすると status code 400 を要望できる。
$ http -v GET http://localhost:4010/ Prefer:code=400
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:4010
Prefer: code=400
User-Agent: HTTPie/2.0.0
---
HTTP/1.1 400 Bad Request
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: *
Connection: keep-alive
Content-Length: 85
Content-type: application/json
Date: Wed, 29 Apr 2020 20:34:58 GMT
{
"errorCode": -81152480,
"errorMessage": "non labore sunt sint Duis",
"moreInfo": "ipsum"
}
ただし、 400 の仕様が記述されていないと動作しないので注意
HTTP/1.1 404 Not Found
Connection: keep-alive
Content-Length: 191
access-control-allow-credentials: true
access-control-allow-headers: *
access-control-allow-origin: *
access-control-expose-headers: *
content-type: application/problem+json
date: Tue, 05 May 2020 08:42:03 GMT
sl-violations: [{"location":["response"],"severity":"Warning","message":"Unable to match the returned status code with those defined in the document: 201"}]
{
"detail": "Requested status code 400 is not defined in the document.",
"status": 404,
"title": "The server cannot find the requested content",
"type": "https://stoplight.io/prism/errors#NOT_FOUND"
}
2. example response を要求
example ID を指定するとそれをお返ししてくれる。あら便利! リクエストの example ID を指定したらリクエストに対してもバリデーションかけてくれると嬉しいかも…?
3. dynamic response を要求
起動時の -d
オプションの有無をこれで上書きできる。
Prefer: dynamic=true
Prefer: dynamic=false
4. x-faker
キーワードを仕様に埋め込んでリアルな dynamic response を。
x-faker
キーワードを OAS のプロパティのスキーマに入れる(format や example と同じ要領で)と、 JSON Schema Faker (実体はどうも Faker.js に依存しているらしい) による、指定フォーマット(メールアドレス、電話番号、等々)のランダムな値の生成ができるらしい。 Faker.js 公式の demo page で各フォーマットがわかり、 JSON Schema Faker で実際に試せる。
これが JSON schema (YAML にて失礼):
type: object
properties:
id:
type: string
pattern: '[0-9a-f]{32}'
name:
type: string
x-faker: random.uuid
phone:
type: string
x-faker: phone.phoneNumber
それに対して生成される JSON object をいくつか:
{
"id": "86efee7471cf7b04fa570e6c68f74e27",
"name": "464ad31c-be66-4168-af5a-a5f366ea6c71",
"phone": "528-042-3204"
}
{
"id": "41f3927da2b6986119360b71e09e2ebc",
"name": "24dca20c-bc30-4ec8-a2e6-bd1d44bef41b",
"phone": "473-093-2555 x19174"
}
request validation
__server
クエリパラメータで OAS に定義されたサーバURLと一致するかどうかのチェックもできるらしいが、わざわざ query を書く時点でちょっと違う気がする。飛ばし先は相変わらずlocalhost:4010
だったりするわけなので。
Validation Proxy
mock と proxy あるうちの mock 側。
base path の考え方
- proxy 自体のベースパス: mock と同じように spec を解釈する
- backend のベースパス: CLI で指定するベースパスがそのまま使われる。
- 例: proxy 起動コマンドが
docker run --rm -it -v $(pwd):/tmp -p 4010:4010 stoplight/prism:3 proxy -h 0.0.0.0 '/tmp/spec.yaml' 'http://example.com/v1/base/'
なら、 proxy にhttp://localhost:4010/cats/{catName}
というフルパスでアクセスがあったら、 backend にはhttp://example.com/v1/base/cats/{catName}
というフルパスでアクセスに行く
- 例: proxy 起動コマンドが
その他使い方
mock は callback にも対応している。 … いや、そもそも OAS での callback の指定の仕方を知らなかった。使うとなれば便利なんだろうなぁ。あんまり対応しているツール無いんじゃなかろうか。
CORS はデフォルトで寛大な設定で、 Allow any method and origin って感じ。これもいじれるっぽい。
複数の OpenAPI documents を mock するなら、 docker-compose とかで頑張れ。 1 container for 1 spec file だ。 nginx の reverse proxy をフロントに、裏に1ファイルずつ prism mock コンテナを用意する、とか。
Postman Collection の JSON から prism mock を生成することもできるらしい。ただし Postman 自身が OpenAPI 準拠ではない機能を持っていたりするので、フル活用は出来ないかも。自分的には Postman はもう API client に成り下がっているので、充実したテストは不要。 (request を collection として保存できたり、環境変数を管理できたり、それらをチームで共有できる点は大変便利に使っているよ。あくまでテスト自動化に使っていないだけ)
mock と proxy を組み合わせる
何ができるかというと、クライアントのリクエストもサーバのレスポンスもバリデーションがかかる。つまり、 spec の request, response の正しさとクライアントの実装が同時に検証される。
- ローカルでそれをやる例として、以下の2つ同時に稼働させれば良い:
- proxy:
docker run --rm -it -v $(pwd):/tmp -p 4011:4010 stoplight/prism:3 proxy -h 0.0.0.0 '/tmp/spec.yaml' 'http://<your_local_if_addr>:4010/'
- mock:
docker run --rm -it -v $(pwd):/tmp -p 4010:4010 stoplight/prism:3 mock -h 0.0.0.0 -d '/tmp/spec.yaml
- proxy: