スクリプトのお勉強 技術

FastAPIでAPIを作ってみる(その1)

投稿日:2020年7月28日 更新日:

勉強として、FastAPIを使用して、実際にAPIを作成し、起動しようと思います。目標としては、本番運用用の設定まで行いたいと思います。

FastAPIとは

FastAPIとは、Pythonによる、Webアプリケーションフレームワークです。以下の特徴があるそうです。

  • 高速
  • コーディング高速化
  • バグの少なさ
  • 直感的
  • 簡単
  • 重複のなさ
  • 堅牢
  • 標準準拠

特に、標準準拠的に、OpenAPIによるドキュメントを自動生成してくれるのが良い感じに見えました。

どんなAPIを作るの?

あるキーワードAを入力したら、もともと持っているキーワードBと組み合わせて、googleで検索できるURL(クエリURL)を返すAPIを作ろうと思います。

例えば、”食べる” というAPIの入力があるとします。
このAPIの内部ではキーワードとして”ラーメン”(=R)を持っていたとします。

その場合、例えば、このAPIのURL「/queryURL/R?q=食べる」にアクセスすると、APIはgoogle検索に”ラーメン 食べる”としたときのURLを返却します。

具体的には以下になります。

{
  queryURL: 'https://www.google.com/search?q=%E9%A3%9F%E3%81%B9%E3%82%8B+%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3&oq=%E9%A3%9F%E3%81%B9%E3%82%8B+%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3'
}

環境

環境は以下を使用します。

  • Python: 3.6.9
  • pipenv: 2020.06
  • FastAPI: 0.59.0
  • nginx: 1.18.0
  • gunicorn: 20.0.4
  • systemd

構成は以下のようになります。

nginx -> (127.0.0.1:28168) ->
                            gunicorn -> FastAPI(pipenv) -> app.py
                            (systemd)

開発環境設定

最初は、以下で環境を設定しました。

$ pipenv install fastapi[all] uvicorn gunicorn sqlalchemy

sqlalchemy は今は使用しませんが、後で使用する予定です。
あと、Python3のバージョンによっては、dataclassesを入れる必要があるかもしれません。

ソース

ソースは以下に置いておきました。

https://github.com/KenichiTanino/query_url_web_api.git

テスト用起動方法

テスト用にAPIを起動するには以下にします。api:appの”api”はモジュールを指します。つまりapp/api.pyになっていたら”app.api”にします。”:app”は属性を指します。属性というのは、実際のところ、FastAPIを指す変数名です。

$ pipenv run uvicorn api:app --reload --host 0.0.0.0

Swagger UI

目玉のOpenAPIによるドキュメントです。

以下にアクセスすると、

http://192.168.132.128:8000/docs

以下のように表示します。以下を自動生成してくれるのはなかなか便利だと思いました。

FastAPIが自動生成したSwagger UI

設定方法

リポジトリのファイルから、本番まで設定する想定で、設定方法を書いていきます。

手順としては以下の流れになります。

  • インストール(git cloneでファイル配置)
  • systemd登録/起動(gunicorn起動)
  • nginx登録

インストール

リポジトリを/usr/local/queryurlにcloneしたとします。

以下のようにインストールします。

### ユーザ作成(www-data:www-data)
$ sudo useradd -U -M -s /sbin/nologin www-data
$ cd /usr/local
$ sudo git clone https://github.com/KenichiTanino/query_url_web_api.git queryurl
$ cd queryurl
$ export PIPENV_VENV_IN_PROJECT=true
$ /usr/local/bin/pipenv sync
$ mkdir log
$ sudo chown -R www-data:www-data /usr/local/queryurl

systemd(gunicorn)

gunicornを起動するsystemdユニットファイルは以下の通りです。

[Unit]
Description = queryURL service ( gunicorn - fastapi )
Requires=queryurl.socket
After = network-online.target
ConditionPathExists = /usr/local/queryurl

[Service]
User=www-data
Group=www-data
WorkingDirectory = /usr/local/queryurl
ExecStart = /usr/local/bin/pipenv run gunicorn --config /usr/local/queryurl/gunicorn.py api:app
ExecReload = /bin/kill -s HUP $MAINPID
ExecStop = /bin/kill -s TERM $MAINPID
PrivateTmp = true

[Install]
WantedBy = multi-user.target

難しい所はありませんが、ExecStartは/usr/local/bin/pipenvを前提としています。環境に合わせて変更してください。

etc/gnucorn.pyは以下にしています。

import multiprocessing
import os

name = "gunicorn"

accesslog = "/usr/local/queryurl/log/log_access.txt"
errorlog = "/usr/local/queryurl/log/log_error.txt"

bind = "127.0.0.1:28168"

worker_class = "uvicorn.workers.UvicornWorker"
workers = multiprocessing.cpu_count() * 2 + 1
worker_connections = 1024
backlog = 2048
max_requests = 5120
timeout = 360
keepalive = 2

debug = os.environ.get("DEBUG", "false") == "true"
reload = debug
preload_app = False
daemon = False

systemd 登録/起動

以下でunitファイルを有効化し、永続的に起動できるようにします。

$ sudo systemctl enable /usr/local/queryurl/etc/queryurl.service
$ sudo systemctl daemon-reload
$ sudo systemctl start queryurl.service

nginx登録

nginx.conf(部分)は以下のようにします。

location /query_url {
    proxy_pass http://127.0.0.1:28168;
    proxy_set_header Host               $host;
    proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host   $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP          $remote_addr;
}

動作確認

動作しているかどうかは、以下で確認します。

$ curl -G "https://www.tech-law-pyscho.info/query_url/query/G" --data-urlencode "q=テスト"
{"queryURL":"https://www.google.com/search?q=%E8%A1%8C%E6%94%BF%E6%9B%B8%E5%A3%AB+%E3%83%86%E3%82%B9%E3%83%88"}

おわりに

ここではまずnginxに登録してアクセスできるところまで設定しました。

次は、このAPIを使用して、Webアプリケーションのプロトタイプを作ってみようと思います。

-スクリプトのお勉強, 技術

執筆者:

関連記事

Djangoアプリサンプル – 画像ファイルアップロード + 顔モザイク(画像アップロード編)

仕事で使用している、Djangoについて、サンプルを作成してみようと思います。ここでは、画像ファイルのアップロードと顔モザイクを行うwebアプリを作成してみようと思います。 この記事ではファイルアップ …

Djangoアプリサンプル – 画像ファイルアップロード + 顔モザイク(統合編)

顔モザイク Djangoアプリ 前々回 前回 を統合して、Djangoアプリを作成してみようと思います。 前提インストール 前回、ubuntu 18を前提に記述しましたが、CentOS7(CentOS …

PythonでAESを使用して暗号/復号する

1.つづき Pythonで、PKCS#12の公開鍵で暗号、秘密鍵で復号するプログラムの続きです。 今回はAESで暗号化/復号を行い、通信しながらRSA暗号/復号,AES暗号/復号を組み合わせたいと思い …

seaborn + Pandas + Python によるグラフ描画(その1: 準備編)

グラフ描画してみよう 今現在の仕事で、グラフ描画する可能性があるので、少し練習してみようと思います。 題材について 突然ですが、私は確定拠出型年金に加入しています。証券会社はSBI証券 にしています。 …

Mojolicious XML-RPC Pluginの開発(1)

はじめに 最近、お仕事関連で、perlとWebアプリケーションを触っています。 両方一度にお勉強、ということで、perlのWAF(Webアプリケーションフレームワーク)を調べてみようと思いました。 こ …