Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Open API Initiative (OAI)が採用したSwaggerをSinatraで試してみる #swagger

f:id:tbpg:20151109225853p:plain

RESTful APIインターフェイスを記述フォーマットの標準化を推進する団体として
Open API Initiative (OAI) が設立されました。
OAI はAPIの記述フォーマットとして Swagger を採用しました。

Swaggerとは?

シンプルで強力なRESTful APIの仕様記述フォーマットです。
これを利用することで、インタラクティブなドキュメントやClinet SDKの生成などを行うことができます。
このドキュメントはComputer / Human Readable なものです。

詳しくはSwagger Officialを参照

トップダウンアプローチ

Swagger Editorを利用してSwaggerの定義を作成し、Swagger Codegen toolsを利用して、
サーバーの実装を生成します。

  • Swagger Editorの編集の様子

f:id:tbpg:20151109225938g:plain

ボトムアップアプローチ

既に実装済みのRESTful API の実装があり、そこからSwaggerの定義を生成したい場合。
トップダウンアプローチと同様に手動で定義することもできるが、SwaggerをサポートしたFrameworkであれば、
Swaggerの定義を自動的に生成できます。
関連ツールの一覧は下記にあります。

Sinatra APIの生成を試行

Swagger EditorでYAMLを作成

リアルタイムで設定内容に対応するドキュメントが表示されます。

swagger: '2.0'
info:
  title: Sample Sinatra API
  description: Swagger Sample for Sinatra
  version: 1.0.0
host: localhost:9292
schemes:
  - http
basePath: /v1
produces:
  - application/json
paths:
  /todos:
    get:
      summary: Todos
      description: |
        TODO List.
      parameters:
        - name: q
          in: query
          description: 検索条件
          required: true
          type: string
      responses:
        '200':
          description: An array of todos
          schema:
            type: array
            items:
              $ref: '#/definitions/Todos'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
definitions:
  Todos:
    type: object
    properties:
      todo_id:
        type: string
        description: 'Unique identifier for Todo.'
      title:
        type: string
        description: Display title of todo.
      description:
        type: string
        description: Description of todo.
      estimate:
        type: number
        description: Description of todo.
  Error:
    type: object
    properties:
      code:
        type: integer
        format: int32
      message:
        type: string
      fields:
        type: string

Swagger EditorでSinatraのコードテンプレートを生成

f:id:tbpg:20151109225904p:plain

こんな感じの構成で生成されます

$ tree
.
└── sinatra-server
    ├── api
    │   └── default_api.rb
    ├── config.ru
    ├── Gemfile
    ├── lib
    │   └── swaggering.rb
    ├── my_app.rb
    └── README.md

APIクライアントを生成します

f:id:tbpg:20151109225912p:plain

こんな感じの構成で生成されます

$ tree
.
├── lib
│   ├── swagger_client
│   │   ├── api
│   │   │   └── default_api.rb
│   │   ├── api_client.rb
│   │   ├── api_error.rb
│   │   ├── configuration.rb
│   │   ├── models
│   │   │   ├── base_object.rb
│   │   │   ├── error.rb
│   │   │   └── todos.rb
│   │   └── version.rb
│   └── swagger_client.rb
└── swagger_client.gemspec

Sinatraサーバー実装

Sinagraが生成したswaggering.rbに以下のコードを追加

  get "/v1/todos" do
    content_type :json
    [
      {
        id: "1",
        title: "todos1",
        description: "desc1",
        estimate: 2
      },
      {
        id: "2",
        title: "todos2",
        description: "desc2",
        estimate: 3
      }
    ].to_json
  end

サーバー起動

  • gemのインストール
$ bundle
$ rackup
$ curl http://localhost:9292/todos
[{"id":"1","title":"todos1","description":"desc1","estimate":2},{"id":"2","title":"todos2","description":"desc2","estimate":3}]

クライントライブラリの利用

自動生成しておいたクライアントライブラリを利用してみます。
API Serverは起動したままにしておきます。

  • 自動生成したRuby Clientをbuild, install
$ gem build swagger_client.gemspec
find: ‘spec/*’: No such file or directory
  Successfully built RubyGem
  Name: swagger_client
  Version: 1.0.0
  File: swagger_client-1.0.0.gem

$ gem install swagger_client-1.0.0.gem
Fetching: ethon-0.8.0.gem (100%)
Successfully installed ethon-0.8.0
Fetching: typhoeus-0.8.0.gem (100%)
Successfully installed typhoeus-0.8.0
Successfully installed swagger_client-1.0.0
Parsing documentation for ethon-0.8.0
Installing ri documentation for ethon-0.8.0
Parsing documentation for typhoeus-0.8.0
Installing ri documentation for typhoeus-0.8.0
Parsing documentation for swagger_client-1.0.0
Installing ri documentation for swagger_client-1.0.0
Done installing documentation for ethon, typhoeus, swagger_client after 3 seconds
3 gems installed
  • Ruby - API Client 経由でAPI Serverを呼び出し

test.rb

require 'swagger_client'
require 'swagger_client/api/default_api'

print SwaggerClient::DefaultApi.new.todos_get({q: "test"})
  • 実行結果
$ ruby test.rb
[#<SwaggerClient::Todos:0x007fda9b01fef0 @title="todos1", @description="desc1", @estimate=2.0>, #<SwaggerClient::Todos:0x007fda9b01fb08 @title="todos2", @description="desc2", @estimate=3.0>]

外部資料