Github: https://github.com/zalando/connexion
接続
ConnexionはFlaskの上にあるフレームワークで、 YAML形式で記述されたAPIのOpenAPI 2.0仕様 (旧称Swagger Spec)に基づいてHTTPリクエストを自動的に処理します。 ConnexionではSwagger仕様書を作成し、エンドポイントをPython関数にマップすることができます。 多くのツールがPythonコードに基づいて仕様を生成するので、これはユニークです。 REST APIについては、必要なだけ詳細に記述することができます。 Connexionは指定したとおりに動作することを保証します。
Connexionをこのようにして作成しました。
- 開発プロセスを簡素化する
- APIがどのように見えるかについての期待を確認する
コネクション機能:
- 仕様に基づいて、要求とエンドポイント・パラメーターを自動的に検証します。
- Web Swagger Console UIを提供します。これにより、APIのユーザーはライブ文書を持ち、APIを通じてAPIのエンドポイントを呼び出すことができます
- OAuth 2トークンベース認証を処理する
- APIのバージョン管理をサポート
- ペイロードの自動シリアル化をサポートします。 エンドポイントがJSONを返すと仕様で定義されている場合、Connexionは自動的に戻り値をシリアル化し、HTTPヘッダーに正しいコンテンツタイプを設定します。
なぜコネクション?
Connexionでは、最初に仕様を記述します。 ConnexionはPythonコードを呼び出し、仕様からコードへのマッピングを処理します。 これは、コードの単一行を記述する前であっても、すべての開発者がAPIの機能を理解できるように仕様を書くことを促します。
複数のチームがAPIに依存する場合は、Connexionを使用してAPIのドキュメントを簡単に送信できます。 これにより、APIが記述した仕様に従うことが保証されます。 これはHugのようなフレームワークが提供するプロセスとは異なるプロセスで、コードを記述した後に仕様を生成します。 コードに基づいて仕様を生成することのいくつかの欠点は、多くの場合、詳細が不足したり、アプリケーションのコードロジックとドキュメントが混在することです。
その他の出典/覚書
- Zalando Techブログの投稿API First
- Swaggerのウェブサイトに掲載されているコネクション
- ブログ記事: 効果的なマイクロサービスをPythonで作る
使い方
前提条件
Python 2.7またはPython 3.4以上
それをインストールする
コマンドラインに次のように入力します。
$ pip install connexion
それを実行する
API YAMLをアプリケーションのルートパスのフォルダ( swagger/
)に配置します。 次に、
import connexion
app = connexion.App(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml')
app.run(port=8080)
サンプル仕様については、 Connexion Pet Storeのサンプルアプリケーションを参照してください。
Connexionを実行して使用することができます。
OAuth 2の認証と認可
Connexionは、3つのOAuth 2処理メソッドの1つをサポートしています。 Connexionでは、APIセキュリティ定義に ‘x-tokenInfoUrl’または ‘x-tokenInfoFunc(またはそれぞれTOKENINFO_URL
またはTOKENINFO_FUNC
env varを設定)をTOKENINFO_URL
必要があります。 ‘x-tokenInfoUrl’には、 トークン情報を検証して取得するためのURLが含まれていなければならず、 ‘x-tokenInfoFuncにはトークン情報を取得するための関数への参照が含まれていなければなりません。 ‘x-tokenInfoUrl’と ‘x-tokenInfoFunc’の両方が使用されている場合、Connexionは関数メソッドに優先順位を付けます。 Connexionは、 Authorization
ヘッダーフィールドにOAuthトークンをRFC 6750 section 2.1で記述されている形式で受け取ることを期待しています。 この側面は、通常のOAuthフローとの大きな違いを表します。
仕様のダイナミックレンダリング
ConnexionはJinja2を使用して、argumentsパラメーターを使用してパラメーターを指定できるようにします。 アプリケーションの仕様引数は、グローバルに(connexion.Appコンストラクタを使用して)、または特定のAPIごとに(connexion.App#add_apiメソッドを使用して)定義できます。
app = connexion.App(__name__, specification_dir='swagger/',
arguments={'global': 'global_value'})
app.add_api('my_api.yaml', arguments={'api_local': 'local_value'})
app.run(port=8080)
値がグローバルおよびAPIの両方に提供される場合、API値が優先されます。
エンドポイントからPythonビューへのルーティング
Connexionは、各操作オブジェクトの operationId
を使用して、どのPython関数が各URLを処理するかを識別します。
明示的ルーティング :
paths:
/hello_world:
post:
operationId: myapp.api.hello_world
http://MYHOST/hello_world
への指定POSTリクエストでこのパスを指定すると、 myapp.api
モジュールのhello_world
関数によって処理されます。 オプションで、操作定義にx-swagger-router-controller
で、 operationId
relativeを作成することができます。
paths:
/hello_world:
post:
x-swagger-router-controller: myapp.api
operationId: hello_world
自動ルーティング
この動作をカスタマイズするために、Connexionでは代替Resolvers
RestyResolverなど)を使用できます。 RestyResolver
は、指定されたエンドポイントのパスとHTTPメソッドに基づいてRestyResolver
を作成します。
from connexion.resolver import RestyResolver
app = connexion.App(__name__)
app.add_api('swagger.yaml', resolver=RestyResolver('api'))
paths:
/:
get:
# Implied operationId: api.get
/foo:
get:
# Implied operationId: api.foo.search
post:
# Implied operationId: api.foo.post
'/foo/{id}':
get:
# Implied operationId: api.foo.get
put:
# Implied operationId: api.foo.put
copy:
# Implied operationId: api.foo.copy
delete:
# Implied operationId: api.foo.delete
RestyResolver
は、仕様で遭遇したoperationId
RestyResolver
に優先RestyResolver
を与えます。 また、 x-router-controller
も尊重しx-router-controller
。 connexion.resolver.Resolver
をインポートおよび拡張して、独自のoperationId
(および関数)解決アルゴリズムを実装することができます。
自動パラメータ処理
Connexionは、エンドポイント仕様で定義されたパラメータを、名前付きパラメータとしてPythonビューの引数に自動的にマッピングします。可能であれば、値のキャストも行います。 ビュー引数と同じ名前のエンドポイントのパラメータを定義するだけです。
たとえば、エンドポイントが次のように指定されているとします。
paths:
/foo:
get:
operationId: api.foo_get
parameters:
- name: message
description: Some message.
in: query
type: string
required: true
ビュー機能:
# api.py file
def foo_get(message):
# do something
return 'You send the message: {}'.format(message), 200
この例では、Connexionは、ビュー関数がmessageという名前の引数を期待していることを自動的に認識し、エンドポイントパラメータメッセージの値をビュー関数に代入します。
警告
エンドポイントで必須ではないパラメータを定義し、Pythonビューに名前のない引数がある場合は、このエンドポイントをパラメータなしで呼び出すたびに「位置指定引数がありません」という例外が発生します。
タイプキャスト
可能な限り、Connexionは引数の値を解析し、関連するPythonネイティブ値に型変換します。 現在利用可能な鋳造品は以下のとおりです。
スワッガータイプ | Pythonタイプ |
---|---|
整数 | int |
文字列 | str |
数 | 浮く |
ブール値 | ブール |
アレイ | リスト |
オブジェクト | dict |
配列型を使用する場合Swagger定義では、認識されないようにcollectionFormatを定義できます。 Connexionは現在、 “pipe”と “csv”のコレクション形式をサポートしています。 デフォルトのフォーマットは “csv”です。
パラメータの検証
Connexionは、クエリおよびフォームデータパラメータに対して厳密なパラメータ検証を適用できます。 これを有効にすると、swagger specに定義されていないパラメータを含む要求は400エラーを返します。 アプリケーションにAPIを追加するときに有効にすることができます:
app.add_api('my_apy.yaml', strict_validation=True)
APIのバージョン管理とベースパス
また、API仕様の最上位レベルでbasePath
を定義することもできます。 これはバージョン管理されたAPIに便利です。 http://MYHOST/1.0/hello_world
から前のエンドポイントを提供するには、 http://MYHOST/1.0/hello_world
に入力します。
basePath: /1.0
paths:
/hello_world:
post:
operationId: myapp.api.hello_world
仕様に基本パスを含めたくない場合は、APIをアプリケーションに追加するときにそれを指定できます。
app.add_api('my_api.yaml', base_path='/1.0')
Swagger JSON
Connexionは、JSON形式のOpenAPI / Swagger仕様を、APIの基本パスのswagger.json
から利用可能にします。
アプリケーションレベルでSwagger JSONを無効にすることができます:
app = connexion.App(__name__, specification_dir='swagger/',
swagger_json=False)
app.add_api('my_api.yaml')
APIレベルで無効にすることもできます:
app = connexion.App(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml', swagger_json=False)
HTTPSサポート
API YAMLファイルのスキームとしてHTTPSを指定する場合、配信されるSwagger UIのすべてのURIはHTTPSエンドポイントです。 問題:実行されるデフォルトのサーバーは、通常のHTTPサーバーです。 つまり、Swagger UIを使用してAPIを使用することはできません。 Connexionを使用してHTTPSサーバを起動する正しい方法は何ですか?
Flaskによって記述された 1つの方法は、次のようになります。
from OpenSSL import SSL
context = SSL.Context(SSL.SSLv23_METHOD)
context.use_privatekey_file('yourserver.key')
context.use_certificate_file('yourserver.crt')
app.run(host='127.0.0.1', port='12344',
debug=False/True, ssl_context=context)
ただし、Connexionはssl_contextパラメータを提供しません。 これは、Flaskはどちらかではありませんが、** kwargsを使用して、基礎となる[werkzeug]( http://werkzeug.pocoo.org/ )サーバーにパラメータを送信します。
スワッガーUIコンソール
APIのSwagger UIは、デフォルトで{base_path}/ui/
ありますbase_path
はAPIの基本パスです。
アプリケーションレベルでSwagger UIを無効にすることができます:
app = connexion.App(__name__, specification_dir='swagger/',
swagger_ui=False)
app.add_api('my_api.yaml')
APIレベルで無効にすることもできます:
app = connexion.App(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml', swagger_ui=False)
必要に応じて、swagger-uiを使用してディレクトリへのパスを明示的に指定して、connexion-embedded swagger-uiディストリビューションを使用しないようにすることができます。 これを行うには、次のオプションを指定する必要があります。
options = {'swagger_path': '/path/to/swagger_ui/'}
app = connexion.App(__name__, specification_dir='swagger/', options=options)
swagger_ui / index.htmlがデフォルトでローカルswagger jsonをロードすることを確認してください。 この目的には、api_url jinja変数を使用できます。
const ui = SwaggerUIBundle({ url: "{{ api_url }}/swagger.json"})
サーバーバックエンド
ConnexionはデフォルトのFlaskサーバーを使用します。 非同期アプリケーションの場合、 TornadoをHTTPサーバーとして使用することもできます。 これを行うには、サーバーをtornado
設定します。
import connexion
app = connexion.App(__name__, specification_dir='swagger/')
app.run(server='tornado', port=8080)
どのようなWSGIコンテナでもFlask WSGIアプリケーションを使用することができます。たとえば、FlaskとuWSGIを使用することができます(これは一般的です)。
app = connexion.App(__name__, specification_dir='swagger/')
application = app.app # expose global WSGI application object
aiohttp
フレームワークをサーバーのバックエンドとしても使用できます。
import connexion
app = connexion.AioHttpApp(__name__, specification_dir='swagger/')
app.run(port=8080)
注: aiohttpハンドラの例も確認してください。
インストールコードをセットアップして実行します。
$ sudo pip3 install uwsgi
$ uwsgi --http :8080 -w app -p 16 # use 16 worker processes
詳細については、 uWSGIのマニュアルを参照してください。
ドキュメンテーション
追加情報については、 Connexionのドキュメントページを参照してください 。
変更点
完全な変更履歴は、 GitHubのリリースページで管理されています 。
コネクション/ TODOに貢献する
あなたのアイデア、問題、プルリクエストを歓迎します。 通常の/標準のGitHubプラクティスに従います。
明示的に明示しない限り、本プロジェクトに本リポジトリ(Zalando SE、Berlin)のスチュワードに意図的に提出された非自明な貢献は、以下のApache License 2.0の条件に従うものとします。著作権情報、条件
TODO
Connexionの一貫性のある貢献者になりたい場合は、寄稿を希望している問題のリストがあります 。
ありがとう
このプロジェクトを担当してくれたConnexionの貢献者全員、そしてSwagger / OpenAPIに感謝したいと思います。
ライセンス
Copyright 2015 Zalando SE
Apache License、Version 2.0(以下「ライセンス」)の下でライセンスされています。 ライセンスに従わない限り、このファイルを使用することはできません。 お客様は、 http://www.apache.org/licenses/LICENSE-2.0でライセンスのコピーを入手することができます 。
適用法または書面による合意が必要な場合を除き、本ライセンスに基づいて配布されるソフトウェアは、明示的または黙示的にいかなる種類の保証または条件もなく「現状有姿」で配布されます。 ライセンスに基づいて許可および制限を規定する特定の言語については、ライセンスを参照してください。