swaggerとは
"API Blueprint"、"RAML"と並ぶAPIドキュメントテーションツール。
RESTful APIの記述標準化を目指す"Open API Initiative"や"Amazon API Gateway"などでも採用されている。
- jsonより書きやすいyaml形式で記述できるwebエディタがある
⇒ Swagger Editor - ソースコードに記述したアノテーションからjson出力することができる
⇒ PHPではswagger-php - swaggerはjson形式(実際にはyamlで書いてjsonで出力)でAPI定義記述するもので、作成したjsonを元にブラウザで参照・実行できるツールがある
⇒ swagger-ui - swaggerのjsonからAPIのコードを生成することができる
⇒ swagger-codegen
今回は、swagger-phpを使用してアノテーションからjsonを生成し、swagger-uiから参照するという流れを試してみる。
前提
- mac OSX 10.13
- nginx + php-fpm + php5.6(FuelPHP) on docker
swagger-php
PHPソース上のアノテーションからswaggerドキュメントを作成してくれるライブラリ。
インストール
composerでインストールする
"require-dev": {
"zircote/swagger-php": "*",
}
アノテーション記法
包括的なドキュメントがないような。。。
-
Getting started
- とりあえず雰囲気はこんな感じ
-
swagger-php/Examples
- 上記のサンプルは2.x系で書かれているので参考になる
-
swagger-explained
- 画面左側に表示されているJSONの各項目にカーソルを合わせると、その項目についての説明を表示してくれる
- 対応するアノテーションも表示してくれる。
-
OPENAPI SPECIFICATION(fka Swagger RESTful API Documentation Specification)
- swagger2.0のマニュアル
-
Swagger-php 1.x documentation
- swagger1.x系の記法なので、json出力時に
@Resource
や@Api
の箇所で deprecated が発生した - swagger-phpで1.x系に対応させる方法は未確認
- swagger1.x系の記法なので、json出力時に
(追記)
アノテーション記法について書きました
⇒ Swagger-PHPでSwagger2.0に対応したアノテーションサンプル
JSON出力
composerで入れたswaggerを実行する
$ fuel/vendor/bin/swagger fuel/app/classes/controller
カレントディレクトリにswagger.json
が出力される。
-o
オプションで出力先を変更可能。
swagger-ui
インストール(docker)
$ git clone https://github.com/swagger-api/swagger-ui.git
$ cd swagger-ui
$ git checkout --force refs/tags/v2.1.4
dockerでビルドできるらしいので試してみたが、npm install
の依存性warningのせい?でエラーになってしまった。
しょうがないのでローカルにインストールした。
一応dockerで試した手順も記載しておく(docker-toolboxを使用)
$ docker-machine create --driver=virtualbox swagger
$ docker-machine env swagger
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/hoge/.docker/machine/machines/swagger"
export DOCKER_MACHINE_NAME="swagger"
# Run this command to configure your shell:
# eval $(docker-machine env swagger)
$ eval $(docker-machine env swagger)
$ docker build -t swagger-ui-builder .
npm installでワーニングが出てしまったので、警告を無視するようにdockerfileを編集してみる。
※macローカルで、npm install
でワーニングが出たが、swagger-uiが動作することは確認済み.
RUN npm install
↓
RUN npm install | true
再度 docker build 実行
$ docker build -t swagger-ui-builder .
npm http 200 https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/express/-/express-4.13.4.tgz
npm http 200 https://registry.npmjs.org/express/-/express-4.13.4.tgz
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /build/npm-debug.log
npm ERR! not ok code 0
---> 43f85ad5f9da
Removing intermediate container c3ff9fac51d6
Step 9 : ADD . /build
---> c475377473f7
Removing intermediate container e91f262ad758
Step 10 : CMD ./node_modules/gulp/bin/gulp.js serve
---> Running in 9ed882094940
---> dd2230ad6a05
Removing intermediate container 9ed882094940
Successfully built dd2230ad6a05
npm install
ではエラーが出力されているが通った。最後の起動は成功しているっぽい。
ただし、次のコンテナ起動がコケてダメだった。。。
$ docker run -p 127.0.0.1:8080:8080 swagger-ui-builder
/bin/sh: 1: ./node_modules/gulp/bin/gulp.js: not found
よく分からないのでローカルにインストールした。
(追記)
docker-composeでコンテナ化しました。
⇒ swagger-ui をdockerで使う
インストール(macローカル)
$ npm install
npm WARN bl@0.7.0 requires a peer of stream-browserify@* but none was installed.
$ npm run build
insatllで1件警告が出たけど、とりあえずbuild通った。
サーバ起動
$ npm run serve
ブラウザで http://localhost:8080
にアクセス。
ドキュメント参照
画面上部のテキストボックス(デフォルトではhttp://petstore.swagger.io/v2/swagger.json
と表示されている)に、対象のjsonへのURLを入力して "Explore"をクリックすればswaggerで記載した内容が表示される。
つまり、読み込む対象のjsonはhttp経由で指定する必要がある。。
ローカルファイルを直接見れないっぽい。。。
なので、先ほど生成したswagger.jsonをドキュメントルートにおいて、http://192.168.99.100:81/swagger.json
という感じで取得しようとしたが、下記のエラーが発生。
Can't read from server. It may not have the appropriate access-control-origin settings.
今回はAPIをVM上に作成していたためCORSエラーが発生してしまった。。。
これについては、とりあえずnginxに下記の設定を行って回避した。
(後に実際APIを叩く際にもCORS対応が必要なのでphp用のロケーションにも設定しておく)
location / {
...
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Origin, Authorization, Accept";
add_header Access-Control-Allow-Credentials true;
...
}
...
location ~ \.php$ {
...
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Origin, Authorization, Accept";
add_header Access-Control-Allow-Credentials true;
...
}
これで、とりあえずjsonの内容がブラウザに表示された。
swagger-uiからAPIの実行
各エンドポイントにあるTry it out!
ボタンで、実際にAPIを実行することができる。
ただし、メソッドがGET
以外の場合、一度OPTIONS
メソッドで疎通確認した後に本来のメソッドで実行するというよく分からない挙動をする。。。
初回のOPTIONS
メソッドによるアクセスについては200系の正常レスポンスを返してあげないと正しく動かないので、OPTIONS
メソッドでアクセスがきたらOKを返すようにする必要がある。
とりあえずnginxの設定で200を返すようにしてみたら、OPTIONS
メソッドのアクセスだけで終わってしまった。。
if ($request_method = OPTIONS) {
return 200;
}
なので、API側でOPTIONS
メソッドだったら処理終了させるようにしたら、その後のPOST
も動いた。
nginxとAPIを別サーバにしているせいかもしれないが、よく分からない。。。
bootprint-swagger
swagger-uiだと、jsonからhtmlを作成しているのでnode上でないと参照できない。。
静的なhtmlが欲しい場合は、変換ツールを使用する。
インストール
$ npm install -g bootprint
$ npm install -g bootprint-swagger
実行
$ mkdir swagger-html
$ bootprint swagger http://192.168.99.100:81/swagger.json swagger-html
Loading bootprint-swagger 0.13.1
Loading bootprint-json-schema 0.8.6
Loading bootprint-base 0.7.2
[ 'swagger-html/index.html',
'swagger-html/main.css',
'swagger-html/main.css.map' ]
出力を一つのファイルにまとめたい場合は、別途html-inline
を使う。
$ npm -g install html-inline
$ html-inline swagger-html/index.html
その他
swagger-to-ramlとかもあるので、RAMLにしてからraml2htmlした方が見やすいHTMLになる気はする。。