9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Myuon Corp.Advent Calendar 2016

Day 3

Swagger を CentOS6.5 上で動かしてみた

Posted at

Myuon Corp. Advent Calendar 2016 3日目です。

Swagger を vagrant で建てた CentOS6.5 上で動かしてみた

Swagger を業務で使ってみようということになり、Vagrant 上に導入してみました。

Vagrant で CentOS6.5 を建てる方法については、割愛して Swagger とはなにか、導入の仕方と動かし方、扱い方をまとめてみようと思います。

Swagger とはなにか

Swagger とは Restful な API 仕様の記法と、記述するためのツール群です。
API 仕様を yamljson で記述することができます。
何より特徴的なのが yaml, json の編集をブラウザ上で実行する事ができ、ライブプレビューで仕様書風なページが表示されることです。
また、記述したものをプレビューされている仕様書風なページ上で実行することができます。

スクリーンショット 2016-12-02 20.44.12.png

実際に作成した仕様書を元に Server, Client のソースコードをジェネレートすることができるみたいですが、そこはまだ触れていないのでいずれまとめたいと思います。

建てた Vagrant の環境

今回、Swagger の Editor を Vagrant で建てようということになり、ミニマムな状態の CentOS (6.5) を建てました。

  • OS

$ cat /etc/redhat-release
CentOS release 6.5 (Final)
$ uname -a
Linux swagger 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux


* 容量

    ```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       7.3G  1.6G  5.4G  24% /
tmpfs           295M     0  295M   0% /dev/shm
vagrant         465G  370G   96G  80% /vagrant

Swagger の導入

Swagger には node.js 製のもの、 javascript 製のものがあるようです。

まずは、エディタを動かしたいので swagger-editor を導入します。

必要なものは以下のものです。

  • nodejs
  • npm
  • wget
  • http-server
  • swagger-editor

上の3つは yum でインストールしちゃいます。

$ sudo yum install -y nodejs
$ sudo yum install -y npm
$ sudo yum install -y wget

次の、 http-server は node.js 製の HTTP サーバです。
npm でインストールします。

$ npm install -g http-server

単に swagger-editor 内の index.html が HTTP サーバ上で動作すれば良いので、手元に rails があれば public の下に swagger-editor を置いても動作します。
とりあえず動かすのが目的であれば、他のもので代用しても問題ありません。

最後に、swagger-editor の取得です。
wget でソースコードの zip をダウンロードします。

$ wget https://github.com/swagger-api/swagger-editor/releases/download/v2.10.4/swagger-editor.zip

ダウンロードしたものは解凍しましょう。

$ unzip ./swagger-editor.zip

Swagger の動かし方

ようやく、swagger-editor を動かす時が来ました。

http-server swagger-editor

実行すると、次のような出力が得られます。

Starting up http-server, serving swagger-editor
Available on:
  http://127.0.0.1:8081
  http://10.0.2.15:8081
  http://192.168.33.52:8081
Hit CTRL-C to stop the server

ブラウザでアクセスすると見事エディタが起動します。
導入はすごく簡単ですね。

Swagger の扱い方

Swagger の扱い方として、次のものを順にまとめます。

  • 書き方
  • Type
  • プロジェクト

書き方

swagger-editor を起動してアクセスすると、まずエディタにはサンプルの yaml が貼り付けられていて、おおよその書き方はそのサンプルのコメントで分かるようになっています。
また、エディタのステータスバーの File > Open Example... から別のサンプルを開くこともできるので、不足分はそちらで補うこともできそうです。

書き方の解説は yaml 形式で、例に上げるサンプルを petstore_full.yaml としてまとめます。

  • 構成


    ルート階層は次の表のようになっています。

    key 用途
    swagger string swagger のバージョン
    info object API の情報
    host string API のホスト
    basePath string API のベースパス
    schemes array 使用可能なスキームのリスト
    paths object API のパスのリスト
    securityDefinitions: object 認証などのセキュリティの定義
    definitions object モデルのリスト

    それぞれの解説をします。

    swagger はそのまんまですね。
    サンプルでは次のようになっています。

swagger: "2.0"


    ---

    **info** は次のような情報を持ちます。

    | key | 型 | 用途 |
    |:--- |:--- |:--- |
    | description | string | API がどういうものなのかの説明文 |
    | version | string | API のバージョン |
    | title | string | API のタイトル (プロジェクト名) |
    | termsOfService | string | 利用規約ページ |
    | contact | object | `name` をキーとした連絡先 |
    | license | object | `name` をキーとしたライセンス名、 `url` をキーとしたライセンス条文のページのリンク |

    ミニマムで設定するのであれば、 `description` , `title` , `version` だけで良さそうです。
    サンプルでは次のようになっています。

    ```
info:
  description: |
    This is a sample server Petstore server.

    [Learn about Swagger](http://swagger.io) or join the IRC channel `#swagger` on irc.freenode.net.

    For this sample, you can use the api key `special-key` to test the authorization filters
  version: "1.0.0"
  title: Swagger Petstore
  termsOfService: http://helloreverb.com/terms/
  contact:
    name: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
**host** , **basePath** はそのまんまですね。
サンプルでは次のようになっています。

```

host: petstore.swagger.io
basePath: /v2


    **schemes** は利用可能なスキームを列挙します。
    サンプルでは次のようになっています。

    ```
schemes:
  - http
これを増やすと、プレビューページで実行する際のスキームの選択肢が増えます。

---

**paths** は一番重要なところです。
次のような情報を持ちます。
※ 階層が深くなるので `.` で連結して階層を表現します。

| key | 型 | 用途 |
|:--- |:--- |:--- |
| /pets/{petId} | string | リソースへのパス |
| /pets/{petId}.get | object | |
| /pets/{petId}.get.tags | array<string> | Swagger の仕様書上でフィルタするためのタグ |
| /pets/{petId}.get.summary | string | エンドポイントに対する概要 |
| /pets/{petId}.get.description | string | エンドポイントに対する説明 |
| /pets/{petId}.get.operationId | string | operationId **FIXME** |
| /pets/{petId}.get.produces | array<string> | 出力可能なコンテンツタイプのリスト |
| /pets/{petId}.get.parameters | array<object> | パラメータの定義のリスト |
| /pets/{petId}.get.parameters[].in | string | パラメータの配置先 `path` か `query |
| /pets/{petId}.get.parameters[].name | string | パラメータ名 |
| /pets/{petId}.get.parameters[].description | string | パラメータの説明 |
| /pets/{petId}.get.parameters[].requied | boolean | 必須かどうか |
| /pets/{petId}.get.parameters[].type | string | 型 |
| /pets/{petId}.get.parameters[].format | string | 型のフォーマット |
| /pets/{petId}.get.response | object | レスポンスの定義 |
| /pets/{petId}.get.response."404" | object | 404 レスポンスの定義 |
| /pets/{petId}.get.response."404".description | string | 404 レスポンスの説明 |
| /pets/{petId}.get.response."200" | object | 200 レスポンスの定義 |
| /pets/{petId}.get.response."200".description | string | 200 レスポンスの説明 |
| /pets/{petId}.get.response."200".schema | object | 200 レスポンスのボディ |
| /pets/{petId}.get.security | array<object> | セキュリティの定義 |
| /pets/{petId}.get.security.api_key | array? | [] を指定すると未指定にできる **FIXME** |
| /pets/{petId}.get.security.petstore_auth | array<string> | 後述の `securityDefinitions` への参照となる `key` |

`/pets/{petId}` のように `{}` を使用することでプレースホルダにすることができます。

`get` の部分は `post` とすることで POST の定義を作成できます。

`tags` は、Swagger のプレビューページでフィルタリングするためのもののようです。
`summary`, `tags`, `produces` はオプショナルです。
`produces` はルート階層に配置することも可能です。

`parameters` に定義するオブジェクトは `in` キーに対して `path` を与えると、path で設置したプレースホルダに対応します。
`in` キーに対して `query` を与えると、 `?parameter.key=` のようなURLのクエリ部に対応します。
`parameters` の `type` は後述します。

`response` の子要素のキーは HTTP ステータスコードか `default` という文字列を指定する必要があります。
`5xx` とかできないのはちょっと不便に思いました。しかも、`default` って、、、。

`security` の子要素は、後述の `securityDefinitions` を参照することができるようです。

サンプルでは次のようになっています。

```

/pets/{petId}:
get:
tags:
- pet
summary: Find pet by ID
description: Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions
operationId: getPetById
produces:
- application/json
- application/xml
parameters:
- in: path
name: petId
description: ID of pet that needs to be fetched
required: true
type: integer
format: int64
responses:
"404":
description: Pet not found
"200":
description: successful operation
schema:
$ref: "#/definitions/Pet"
"400":
description: Invalid ID supplied
security:
- api_key: []
- petstore_auth:
- write_pets
- read_pets


    ---

    **securityDefinitions** は次のような情報を持ちます。

    | key | 型 | 用途 |
    |:--- |:--- |:--- |
    | api_key | object | api_key オブジェクトの定義 |
    | api_key.type | string |  **FIXME** |
    | api_key.name | string |  **FIXME** |
    | api_key.in | string |  **FIXME** |
    | petstore_auth | object |  **FIXME** |
    | petstore_auth.type | string | 認証方式 |
    | petstore_auth.authorizationUrl | string | 認証を行うページへのURL |
    | petstore_auth.flow | string | **FIXME** |
    | petstore_auth.scopes | array<string> | **FIXME** |

    全体的に未確認なので、早急に確認してまとめたいと思います。
    サンプルでは次のようになっています。

    ```
securityDefinitions:
  api_key:
    type: apiKey
    name: api_key
    in: header
  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
---

**definitions** はいわゆる **モデル** の定義です。
次のような情報を持ちます。

| key | 型 | 用途 |
|:--- |:--- |:--- |
| Pet | object | Pet オブジェクトの定義 |
| Pet.type | string | Pet オブジェクトの型 |
| Pet.required | array<string> | Pet オブジェクトのプロパティの内必須なもののキーのリスト |
| Pet.properties | object | Pet オブジェクトのプロパティの定義 |
| Pet.properties.id | object | Pet オブジェクトのプロパティ `id` の定義 |
| Pet.properties.id.type | string | Pet オブジェクトのプロパティ `id` の型 |
| Pet.properties.id.format | string | Pet オブジェクトのプロパティ `id` のフォーマット |
| Pet.properties.name | string | Pet オブジェクトのプロパティ `name` の定義 |
| Pet.properties.name | string | Pet オブジェクトのプロパティ `name` の定義 |
| Pet.properties.name.type | string | Pet オブジェクトのプロパティ `name` の型 |
| Pet.properties.name.example | string | Pet オブジェクトのプロパティ `name` の例 |

ルート階層のキー名がモデル名になります。
具体的なところは `type` の説明を参照してください。

サンプルでは次のようになっています。

```

Pet:
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: "#/definitions/Category"
name:
type: string
example: doggie
photoUrls:
type: array
items:
type: string
tags:
type: array
items:
$ref: "#/definitions/Tag"
status:
type: string
description: pet status in the store


* **Type**

    ---

    type には 次のものがあります。

    * string
    * float
    * boolean
    * array<?>
    * integer
    * object

    `string` , `float` , `boolean` , `array` は特に解説することはありません。
    上の解説の中には出てきませんでしたが `float` も利用できます。
    [Yaml: types](http://yaml.org/type/) を参照してください。
    ※ rails で yaml を利用する分には気づきませんでしたが、 キーに対して子要素もない、設定値もないと言うのは許可されないようです。

    `integer` には `format` がセットになります。
    `format` をキーとして、 `int32` や `int64` を指定する事ができます。

    `object` はいわゆるハッシュです。

    いずれもキーを `$ref` とすることで、設定値を参照にすることができます。
    この時の設定値は例えば `"#/definitions/Pet"` のようになります。

* **プロジェクト**

    ---

    swagger を npm でインストールすると、`swagger` コマンドが利用できるようになります。

    この `swagger` コマンドには `project` という、サブコマンドがあり、次の機能があります。

    ```
  Commands:

    create [options] [name]              Create a folder containing a Swagger project
    start [options] [directory]          Start the project in this or the specified directory
    verify [options] [directory]         Verify that the project is correct (swagger, config, etc)
    edit [options] [directory]           open Swagger editor for this project or the specified project directory
    open [directory]                     open browser as client to the project
    test [options] [directory_or_file]   Run project tests
    generate-test [options] [directory]  Generate the test template
肝となる `edit` は、どうもブラウザを起動して swagger-editor を開くもののようで、Vagrant で建てた VM では次のようなエラーが出ました。

```

$ swagger project edit
Starting Swagger Editor.
Opening browser to: http://127.0.0.1:43390/#/edit
{ [Error: Command failed: /bin/sh: xdg-open: command not found
] killed: false, code: 127, signal: null }


    いずれ解決してやりたいと思います。
    それはさておき、ひとまずプロジェクトを作ります。

    次のコマンドで、プロジェクトを作成することができます。

    ```
swagger project create <プロジェクト名>
このコマンドを実行すると、次のような内容物を持つディレクトリが生成されます。

```

$ ls -l
total 28
drwxr-xr-x 6 vagrant vagrant 4096 Dec 2 05:11 api
-rw-r--r-- 1 vagrant vagrant 546 Dec 2 05:11 app.js
drwxr-xr-x 2 vagrant vagrant 4096 Dec 2 05:11 config
drwxrwxr-x 6 vagrant vagrant 4096 Dec 2 05:11 node_modules
-rw-r--r-- 1 vagrant vagrant 425 Dec 2 05:11 package.json
-rw-r--r-- 1 vagrant vagrant 31 Dec 2 05:11 README.md
drwxr-xr-x 3 vagrant vagrant 4096 Dec 2 05:11 test


    作成した swagger の定義ファイルは、 `./api/swagger/` に配置します。

    Git 管理に載せる場合は、まとまっていたほうがスッキリするのでひとまずこのプロジェクトにしたもので扱う予定です。
    もっといい方法がわかったらまとめたいと思います。

    また、他の機能はまだ試せていないので、そちらも試してまとめる予定です。

## まとめ

実際、swagger-editor は日本語に弱いらしく、変な入力になることが多々あります。
あまり使いやすいとは言いづらいですが、候補も出ますし、たまにテキスト全体をカット&ペーストすればエラーもちゃんと出してくれます。

プレビューのページはモデルあたりは非常に見難く、そのまま PDF化すれば納品物にできるぜというものではありません。

ドキュメント化という点では Swagger2Markup などの別のツールもあるみたいですが、まだ触れていないので色々試してまとめていきたいと思います。

それと、こういうものこそ Docker と連携しやすいっぽいですね。

まぁ、何にしろ yaml で記述できる手軽さは良いですね。
ちゃんとメンテされるドキュメンテーションへの第一歩ということで。

---

明日は @nullpopon@github さんです。
どんなことを記事にしてくれるのか楽しみです。

<!--
これを例に構築してみたい
curl -i "https://api.github.com/search/code?q=struct+in:file+language:cpp+repo:boostorg/hana"
-->
9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?