Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Swaggerを利用した新規サービス開発

4,262 views

Published on

API Meetup Tokyo #18

Published in: Technology
  • Be the first to comment

Swaggerを利用した新規サービス開発

  1. 1. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを利用した 新規サービス開発 株式会社レコチョク 事業システム推進部 ミュージックアーキテクトグループ 松木 佑徒
  2. 2. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 自己紹介 2 職業:フルスタックエンジニア(自称) 言語:C# (2008~2010) -> Java (2011~2015) -> Python (2016~) 趣味:ドラム / ジャグリング Yuto Matsuki @yustam_jp id:yustam 2008: 某SIerにてシステムエンジニアとして色々な現場で仕事をする 2014: 株式会社レコチョクに転職 2014-2015: レコチョクの楽曲DB周辺のバッチなどをAWS環境上に再構築 2016-: 新サービスWIZYの開発リーダーとしてWebの開発に携わる 最近は研究開発的な事もしています。
  3. 3. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 レコチョクについて 3 https://eggs.mu http://playpass.jp 2015/02サービス開始 2016/03サービス開始
  4. 4. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 WIZYについて 4 2016/08サービス開始 https://wizy.jp
  5. 5. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 WIZYのシステム構成 5
  6. 6. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 WIZYを支える技術 6
  7. 7. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swagger 7
  8. 8. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを採用した経緯① 8 • re:Invent 2015 Bootcampで初めてSwaggerに触れる • Swagger Api Gateway Importerを使用したハンズオン • 用意されたSpecを利用してツールでAPI Gatewayにデ プロイするというもの • サーバレスという概念が出て来て間もない頃で非常に 画期的な印象
  9. 9. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを採用した経緯② 9 • 2015年末新規サービス開発のプロジェクトが始まる • はじめてフロントのシステムを担当することに • 最初のプロトタイプ開発は1人で • 仕様書はExcelなどで書きたくない • 書くならコードの自動生成/再利用性のあるもの • 個人的にRAMLを使ったことがあったが • CodeGeneratorがPythonに対応している • Open API Initiativeが立ち上がりSwaggerを推し始めた
  10. 10. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを採用した経緯 ③使ってみる 10 • 簡単なSwaggerSpecをYAMLで作成 /projects/{project_id}: get: summary: プロジェクト取得 tags: - Project parameters: - name: project_id in: path description: プロジェクトID required: true type: integer responses: 200: description: プロジェクト schema: $ref: '#/definitions/project' project: type: object properties: id: type: integer description: プロジェクトID user_id: type: integer description: ユーザID ... paths: definitions:
  11. 11. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを採用した経緯 ③使ってみる 11 • CodeGeneratorでPythonクライアントを生成 • definitionで定義したオブジェクトをそのままJSON化 • レスポンスはdefinitionsのオブジェクトで受け取れる import swagger_client as sw project_api = sw.ProjectApi(api_client=api) project = project_api.projects_project_id_get(project_id) print(type(project)) print(type(project.end_time)) <class 'swagger_client.models.project.Project'> <class 'datetime.datetime'>
  12. 12. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを採用した経緯 ③使ってみる 12 • JSON Web Tokenを利用した認証 ApiKey: type: apiKey name: Authorization in: header securityDefinitions: /authenticate: post: summary: 認証API tags: - Auth parameters: - name: authenticate in: body required: true schema: $ref: '#/definitions/authenticate' responses: 200: description: トークン schema: $ref: '#/definitions/token' paths: authenticate: type: object properties: key: type: string description: 認証キー secret: type: string format: string description: 認証シークレット token: type: object properties: access_token: type: string description: 認証トークン definitions:
  13. 13. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを採用した経緯 ③使ってみる 13 • JSON Web Tokenを使用した認証を採用 import swagger_client as sw auth_api = sw.AuthApi(sw.ApiClient(API_HOST)) auth = sw.Authenticate(key='user',secret='hogehoge') resp = auth_api.authenticate_post(authenticate=auth) api = sw.ApiClient(host=API_HOST, header_name='Authorization', header_value='JWT %s' % resp.access_token) project_api = sw.ProjectApi(api_client=api) project = project_api.projects_project_id_get(project_id) curl-X POST -d '{"key":"user","secret":"hogehoge"}' http://${API_HOST}/authenticate curl -X GET -H "Authorization: JWT ${JWT_TOKEN}" http://${API_HOST}/projects/${PROJECT_ID}
  14. 14. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 WIZYにおけるSwagger 14 • Swaggerの仕様バージョン2.0 • 開発言語はPython • API側のフレームワークはFlask • APIの認証はFlask-JWTを使用したJWTトークン認証 • 2017年2月時点でAPI数は 63 (pathベースで38)
  15. 15. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swagger Code Generator 15 YAMLで仕様を管理。YAMLから生成 https://github.com/swagger-api/swagger-codegen html python /projects/{project_id}: get: summary: プロジェクト取得 tags: - Project parameters: - name: project_id in: path description: プロジェクトID required: true type: integer responses: 200: description: プロジェクト schema: $ref: '#/definitions/project'
  16. 16. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 WIZYの開発手法 16 1. 機能要件に従ってテーブル定義等の仕様を決める 2. フロントの要件に従ってAPI仕様をSwagger Specで書く 3. Swagger Specに従ってAPIを実装 4. Swagger Code Generatorでクライアントを生成 5. 生成したクライアントを使用してフロントのアプリを実装 web api client cache database spec
  17. 17. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを使って良かったこと(開発) 17 APIの仕様レビューがYAMLファイル上で行える • diffで比較できるのでレビュー漏れが無い • JSONよりYAMLの方が書き方に個人差が出ないのでオススメ
  18. 18. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを使って良かったこと(開発) 18 書式が決まっているのでAPIに必要な情報について曖昧さがない 実装前にある程度挙動を確認できるので手戻りが防げる APIの開発者とクライアント側の開発者が並行で作業できる 他との矛盾/命名規則の違反などを発見しやすい 他のpaths/definitionsを再利用できる /projects/{project_id}: get: summary: プロジェクト取得 tags: - Project parameters: - name: project_id in: path description: プロジェクトID required: true type: integer responses: 200: description: プロジェクト schema: $ref: '#/definitions/project'
  19. 19. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを使って良かったこと(開発) 19 そのままコードになるのでレビューした内容とコードに差がない ドキュメントにもなるのでコードとドキュメントの乖離がない
  20. 20. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを使って良かったこと(運用) 20 Web/APIを分離してバージョン管理しやすくなる SwaggerSpecに変更がある場合のみAPI仕様に変更がある swaggerのtags webのtags apiのtags× ×
  21. 21. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを使って良かったこと(運用) 21 Blue-Green Deploymentにより無停止でバージョンアップ可能に 本番環境ELB API-ELB API v1.0 API v1.1ステージ環境ELB Web v2.0 Web v2.1 しかしAPIに互換性がない場合は並行稼動できない…
  22. 22. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerを使って良かったこと(運用) 22 APIのインタフェース仕様の変更が一目でわかるので 前のバージョンと互換性があるかの判断が簡単になる → pathの追加だけであれば問題ない。など 差分がない場合は仕様に変更がないことが保証されるが ソート順などは表現されないのでインタフェース以外の 修正は個別で判断する必要がある
  23. 23. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 「operationId」の定義は必要か 23 https://apihandyman.io/writing-openapi-swagger-specification-tutorial-part-7-documentation/ paths: /persons: parameters: - $ref: '#/parameters/userAgent' get: summary: Gets some persons description: Returns a list containing all persons. The list supports paging. operationId: searchUsers [main] WARN io.swagger.codegen.DefaultCodegen - Empty operationId found for path: post /projects/{project_id}/items. Renamed to auto-generated operationId: projectsProject_idItemsPost 「operationId」はAPI単位にユニークな名前をつけるもの 書かないとCodeGeneratorに怒られます。。
  24. 24. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 Swaggerの使い方について今後の課題① 24 # operationId未指定の場合 projects = project_api.projects_get(limit=10) # operationIdを指定した場合 projects = project_api.search_projects(limit=10) ルールを作るとしたら • 「GET /XXXs」=>「search_XXXs」 • 「GET /XXXs/{YYY}」 => 「get_XXX_by_YYY」 • 変えたい場合もある。POST/PUT場合はどうする。。? APIのpathとは別でルールを考える必要がありそう Pythonクライアントの場合は自動でメソッド名が決まる
  25. 25. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 25 • OpenAPI 3.0 への移行 • 全体の99%を占めるpaths/definitionsに大きな変更なし? • definitionsはcomponentsの配下に移動 • pathsはそのままに見えます… https://www.openapis.org/news/blogs/2016/10/tdc-structural-improvements-explaining-30-spec-part-2 今後の課題(3.0対応)
  26. 26. © Recochoku Co.,Ltd. Proprietary and Confidential 2017/02/07 26 ご静聴ありがとうございました!

×