はじめに
OpenAPI 界隈では Hello World
の代わりにペットストアを開業することになっているらしいのでやってみた(みんな知ってる petsoter.yaml
から Prism
でモックサーバを立ち上げて遊びます)
Prism
-
Prism は、OpenAPI仕様の
yaml
やjson
を読み込んでモックサーバを立ててくれます - モックサーバに向かってHTTPリクエスト投げると、それなりにいい感じの応答をしてくれます
- モックなんでロジックはありませんが、HTTPヘッダ・認証・データのフォーマットチェックなどそれなりにやってくれます
petsoter.yaml
を読み込みつつ Prism
を立ち上げる
- おもむろに
docker
でいきます
$ docker run --rm -it -p 4010:4010 stoplight/prism:3 mock -d -h 0.0.0.0 https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml
[1:54:08 AM] › [CLI] … awaiting Starting Prism…
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/pet
[1:54:09 AM] › [CLI] ℹ info PUT http://0.0.0.0:4010/pet
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/pet/findByStatus
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/pet/findByTags
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/pet/303
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/pet/174
[1:54:09 AM] › [CLI] ℹ info DELETE http://0.0.0.0:4010/pet/790
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/pet/574/uploadImage
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/store/inventory
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/store/order
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/store/order/2
[1:54:09 AM] › [CLI] ℹ info DELETE http://0.0.0.0:4010/store/order/et
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/user
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/user/createWithArray
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/user/createWithList
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/user/login?username=et&password=libero
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/user/logout
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/user/voluptatibus
[1:54:09 AM] › [CLI] ℹ info PUT http://0.0.0.0:4010/user/reiciendis
[1:54:09 AM] › [CLI] ℹ info DELETE http://0.0.0.0:4010/user/quae
[1:54:09 AM] › [CLI] ▶ start Prism is listening on http://0.0.0.0:4010
-
-d
つけておくと、ランダムにそれっぽいレスポンスデータを返してくれる
curl
投げつける
GET
する
$ curl -s -H 'api_key: special-key' -H "Accept: Application/json" localhost:4010/pet/1 | json_pp
{
"category" : {
"id" : 7155740,
"name" : "mollit in"
},
"id" : 87883213,
"name" : "eiusmod dolor in sed id",
"photoUrls" : [
"est Ut cupidatat incididunt tempor",
"ullamco ut ea ex veniam",
"aliquip mollit proident sit",
"minim ullamco id et",
"ut labore non magna"
],
"status" : "sold",
"tags" : [
{
"id" : 35811162,
"name" : "et cupidatat"
},
{
"id" : -26616885,
"name" : "sint ut non"
}
]
}
-
-H 'api_key: special-key'
しないと認証できない1
APIキーがないと
$ curl -s -H "Accept: Application/json" localhost:4010/pet/1 | json_pp
{
"detail" : "Your request does not fullfil the security requirements and no HTTP unauthorized response was found in the spec, so Prism is generating this error for you.",
"status" : 401,
"title" : "Invalid security scheme used",
"type" : "https://stoplight.io/prism/errors#UNAUTHORIZED"
}
-
-H "Accept: Application/json"
としないとxml
でレスポンスが返ってくる
Acceptを指定しないと
$ curl -X GET -H 'api_key: special-key' -H 'Content-Type: application/json' localhost:4010/pet/414
<xml><id>0</id><category><id>0</id><name>string</name></category><name>doggie</name><photoUrls>string</photoUrls><tags><id>0</id><name>string</name></tags><status>available</status></xml>d030
POST
する
-
POST
はデフォルトで認証周りがOAuth
になって面倒。今回のポイントはそこじゃないので、認証をスキップするようにpetstore.yaml
を書き換えます。大胆にコメントアウト - ちなみにここ
securityDefinitions:
でリクエストのヘッダに渡すべきAPIキーの設定もされている
petstore.yaml
securityDefinitions:
petstore_auth:
# type: oauth2
# authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
# flow: implicit
# scopes:
# 'write:pets': modify pets in your account
# 'read:pets': read your pets
api_key:
type: apiKey
name: api_key
in: header
- さらに、
200 OK
の処理が定義されていないようなので(結構いいかげんやな..)、付け足しておきます -
/pet:
のresponses:
に'200':
を設定してみます
petstore.yaml
responses:
'200':
description: A pet added
schema:
type: array
items:
$ref: '#/definitions/Pet'
'405':
description: Invalid input
-
petstore.yaml
を読み込みます2
$ docker run --rm -it -p 4010:4010 -v $PWD:/tmp stoplight/prism:3 mock -d -h 0.0.0.0 /tmp/petstore.yaml
[1:54:08 AM] › [CLI] … awaiting Starting Prism…
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/pet
[1:54:09 AM] › [CLI] ℹ info PUT http://0.0.0.0:4010/pet
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/pet/findByStatus
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/pet/findByTags
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/pet/303
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/pet/174
[1:54:09 AM] › [CLI] ℹ info DELETE http://0.0.0.0:4010/pet/790
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/pet/574/uploadImage
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/store/inventory
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/store/order
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/store/order/2
[1:54:09 AM] › [CLI] ℹ info DELETE http://0.0.0.0:4010/store/order/et
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/user
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/user/createWithArray
[1:54:09 AM] › [CLI] ℹ info POST http://0.0.0.0:4010/user/createWithList
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/user/login?username=et&password=libero
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/user/logout
[1:54:09 AM] › [CLI] ℹ info GET http://0.0.0.0:4010/user/voluptatibus
[1:54:09 AM] › [CLI] ℹ info PUT http://0.0.0.0:4010/user/reiciendis
[1:54:09 AM] › [CLI] ℹ info DELETE http://0.0.0.0:4010/user/quae
[1:54:09 AM] › [CLI] ▶ start Prism is listening on http://0.0.0.0:4010
- ここまできたら、あとはここで定義されているフォーマットで JSON を用意して
pet.json
{
"category" : {
"id" : 0,
"name" : "string"
},
"id" : 0,
"name" : "doggie",
"photoUrls" : [
"string"
],
"status" : "available",
"tags" : [
{
"id" : 0,
"name" : "string"
}
]
}
- 投げつけます
$ curl -X POST -H "accept: application/json" -s "localhost:4010/pet" -H "Content-Type: application/json" -d @pet.json | json_pp
[
{
"category" : {
"id" : 0,
"name" : "string"
},
"id" : 0,
"name" : "doggie",
"photoUrls" : [
"string"
],
"status" : "available",
"tags" : [
{
"id" : 0,
"name" : "string"
}
]
}
]
-
-H "Content-Type: application/json"
がないとエラーになる
Content-Typeがないと
$ curl -X POST -H "accept: application/json" -s "localhost:4010/pet" -d @pet.json | json_pp
{
"detail" : "Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.",
"status" : 422,
"title" : "Invalid request body payload",
"type" : "https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY",
"validation" : [
{
"code" : "required",
"location" : [
"body"
],
"message" : "should have required property 'name'",
"severity" : "Error"
},
{
"code" : "required",
"location" : [
"body"
],
"message" : "should have required property 'photoUrls'",
"severity" : "Error"
}
]
}
- サーバ側もこんな
200 OK
な感じ。よしとしましょう
[1:30:59 AM] › [HTTP SERVER] post /pet ℹ info Request received
[1:30:59 AM] › [NEGOTIATOR] ℹ info Request contains an accept header: application/json
[1:30:59 AM] › [VALIDATOR] ✔ success The request passed the validation rules. Looking for the best response
[1:30:59 AM] › [NEGOTIATOR] ✔ success Found a compatible content for application/json
[1:30:59 AM] › [NEGOTIATOR] ✔ success Responding with the requested status code 200
- さっきのところで、認証をコメントアウトしないとこんな感じになるでしょう
認証をコメントアウトしないと
$ curl -X POST -d @pet.json -s -H 'api_key: special-key' -H "Accept: Application/json" localhost:4010/pet/1 | json_pp
{
"detail" : "Your request does not fullfil the security requirements and no HTTP unauthorized response was found in the spec, so Prism is generating this error for you.",
"headers" : {
"WWW-Authenticate" : "OAuth2"
},
"status" : 401,
"title" : "Invalid security scheme used",
"type" : "https://stoplight.io/prism/errors#UNAUTHORIZED"
}
- また
'200':
を設定しないとこんなかんじになるでしょう。特に問題はないですが、成功した雰囲気がでません
200を設定しないと
$ curl -X POST -H "accept: application/json" -s "localhost:4010/pet" "accept: application/json" -H "Content-Type: application/json" -d @pet.json | json_pp
{
"detail" : "",
"status" : 500,
"title" : "No response in the range 200-299 defined",
"type" : "https://stoplight.io/prism/errors#NO_SUCCESS_RESPONSE_DEFINED"
}
よし、だいたいわかった。先に進めそうです。