OpenAPI Generator for Flask

メモ

簡単な動作確認

ひとまず分かりやすかった OpenAPI GeneratorでPython Web API構築 をそのまま試す。

1
2
3
4
5
6
7
$ mkdir -p  ~/Sources/OpenAPIGenFlaskSample/original
$ cd ~/Sources/OpenAPIGenFlaskSample/original
$ cat << EOF > openapi.yaml

(snip)

EOF

openapi.yamlの中身は OpenAPI GeneratorでPython Web API構築 に記載されている。

1
2
3
$ mkdir -p server client
$ docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i /local/openapi.yaml -g python-flask -o /local/server
$ docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i /local/openapi.yaml -g go -o /local/client

今回用があるのはサーバ側のPython実装(Flask)の方なので、そちらを確認する。 記事にもあるが以下のようなファイルが生成されているはず。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ tree
.
├── Dockerfile
├── README.md
├── git_push.sh
├── openapi_server
│   ├── __init__.py
│   ├── __main__.py
│   ├── controllers
│   │   ├── __init__.py
│   │   ├── security_controller.py
│   │   └── stock_price_controller.py
│   ├── encoder.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── base_model.py
│   │   ├── error.py
│   │   ├── ok.py
│   │   └── stock_price.py
│   ├── openapi
│   │   └── openapi.yaml
│   ├── test
│   │   ├── __init__.py
│   │   └── test_stock_price_controller.py
│   ├── typing_utils.py
│   └── util.py
├── requirements.txt
├── setup.py
├── test-requirements.txt
└── tox.ini

まずは、 __main__.py を見てみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python3

import connexion

from openapi_server import encoder


def main():
app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder
app.add_api('openapi.yaml',
arguments={'title': 'Stock API'},
pythonic_params=True)

app.run(port=8080)


if __name__ == '__main__':
main()

上記の通り、 connexionを用いていることがわかる。 connexionはFlaskで動作する、APIとpython関数をマッピングするためのパッケージである。 connexionについては、 connexionを使ってPython APIサーバのAPI定義と実装を関連付ける のような記事を参考にされたし。

openapi_server/controllers/stock_price_controller.py を確認する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import connexion
from typing import Dict
from typing import Tuple
from typing import Union

from openapi_server.models.error import Error # noqa: E501
from openapi_server.models.stock_price import StockPrice # noqa: E501
from openapi_server import util


def stock_price(security_cd): # noqa: E501
"""株価取得

現在の株価を取得する # noqa: E501

:param security_cd: 証券コードを指定する
:type security_cd: str

:rtype: Union[StockPrice, Tuple[StockPrice, int], Tuple[StockPrice, int, Dict[str, str]]
"""
return 'do some magic!'

operationId にて指定した名称がコントローラのメソッド名に反映されている。

parameters にて指定したパラメータがコントローラの引数になっていることが確認できる。

components にて指定したスキーマに基づき、openapi_server/models 以下に反映されていることが分かる。 今回の例だと、戻り値用の StockPrice やOK、Errorが定義されている。 なお、これはOpenAPIにて生成されたものであり、それを編集して使うことはあまり想定されていないようだ。

openapi_server/util.py にはデシリアライザなどが含まれている。

さて、記事通り、Dockerで動かしてみる。

1
2
$ docker build -t openapi_server .
$ docker run -p 8080:8080 openapi_server

試しに、適当な引数を与えて動かすと、実装通り戻り値を得られる。

1
2
$ curl http://localhost:8080/v1/sc/4721/stockPrice
"do some magic!"

なおDockerfileはこんな感じである。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FROM python:3-alpine

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY requirements.txt /usr/src/app/

RUN pip3 install --no-cache-dir -r requirements.txt

COPY . /usr/src/app

EXPOSE 8080

ENTRYPOINT ["python3"]

CMD ["-m", "openapi_server"]

Docker化しなくてもそのままでも動く。 ここでは一応venvを使って仮想環境を構築しておく。

1
2
3
4
$ python -m venv venv
$ . venv/bin/activate
$ pip install -r requirements.txt
$ python -m openapi_server

参考

記事

共有