FASTAPIでさくっと構築。

# 経緯
個人WebサーバにPythonで書いたAI機能をデプロイしようとしたところ500エラーが発生しました。原因を探ってみたところスペック不足であることが分かりました。機能を絞った軽量化の悪あがきをしてみたもののうまくいかなかったため、webサーバへのデプロイは諦めてFASTAPIを使ってAPIを作ってみることにしました。

## FASTAPIとは

https://fastapi.tiangolo.com/ja/

**ChatGPT様より**
>FastAPIは、Pythonで現代的で、高速(高パフォーマンス)で、Web APIを構築するためのフレームワークです。その名前の通り、API開発を"Fast"(速く)行うことを主眼に置いて設計されています。

>FastAPIの主な特徴は以下の通りです：
>1. **高パフォーマンス**: Starlette(ASGIサーバー)による非同期処理のサポートにより、ハイパフォーマンスなAPIを作成することができます。Pythonフレームワークの中でも最速レベルのパフォーマンスを持っています。
>2. **素早い開発**: FastAPIは、Python3.6以降の型ヒントを活用して、パラメータとリクエストボディの自動バリデーション、データシリアライゼーション、データ変換を提供します。これにより開発スピードを向上させると同時にバグの数を減らします。
>3. **使いやすい**: FastAPIは、APIの構築とテストを簡単に行えるように設計されています。また、OpenAPI（以前はSwaggerとして知られていました）とJSON Schemaの標準を自動的に使用して、対話式のAPIドキュメントを生成します。
>4. **堅牢な**: FastAPIは、型ヒントと自動バリデーションにより、コードが期待通りに動作することを確認します。これにより、APIが生産環境で失敗する可能性を最小限に抑えることができます。
>5. **モダン**: FastAPIは、Pythonの非同期処理やコルーチンのサポートをフルに活用しています。これにより、非同期データベースへの接続や非同期I/O操作を行うことが容易になります。
>6. **シンプルで直感的**: FastAPIは、Pythonicなアプローチを取り、コードが可能な限り明確で理解しやすいことを重視しています。
>これらの特徴により、FastAPIは現代のウェブアプリケーション開発における重要な選択肢となっています。

**簡単に早いAPIが構築できるようです。**

## 構築手順
FASTAPI、Uvicornをインストールします。

```
pip install fastapi
pip install uvicorn
```

FASTAPIのコードmain.pyの作成します。
今回はテキストを受けて変換したテキストを返す機能なのでChatbotと仮定してChatGPTに書かせました。
    
```
#Fast API
from fastapi import FastAPI
from pydantic import BaseModel
　省略
app = FastAPI()
　省略
    
class Message(BaseModel):
    message: str
    
@app.post("/chatbot")
async def chatbot(message: Message):
    user_message = message.message
    response = 省略(str(user_message))
    return {
        "messages": [
            {"sender": "user", "text":user_message}, 
            {"sender": "bot", "text": response}
            ]
            }
```
pydanticを使って型を指定すると良いようです。

uvicornを立ち上げてローカルで確認します。
    
```
uvicorn main:app --reload
```
http://127.0.0.1:8000/docs
にアクセスし動作確認できます。

動作確認できたら外部との接続設定を行います。

:::note warn
 ここからはセキュリティリスクが高めるので自己責任で
:::    

サーバとして立ち上げるポート番号を決定。
デフォルトは8000番です。
    
Webサーバ側の対象のコードにAPIの設定を行います。
```
http://グローバルアドレス:8000　
```
外部IPアドレスは各自で変更してください。
ルータにフォワーディング設定を行います。
サーバのローカルアドレスとポート番号を設定します。　
    
  イメージ
    
    　　　　　　①　　　　　　　　　　②
    web　→　ルータ　→　サーバ
    
    ①グローバルアドレス:8000
    
    ②ローカルルアドレス:8000

uvicornをローカル以外から受け付けるように立ち上げます。
```
uvicorn main:app --host 0.0.0.0 --port 8000
```
ここまでWindowsPCでテストで実行しましたが、立ち上げっぱなしにしたいので、JETSONを使って常時立ち上げておくことにしました。Nginxでプロキシを間に噛ませました。

### プロキシ
プロキシを8000、FASTAPIを8001とします。
Nginx をインストールします。
    
```
sudo apt install nginx
```
Nginx 設定ファイルを作成します。

```
sudo nano /etc/nginx/sites-available/my-fastapi
```

Nginx 設定内容
```
    server {
        listen 8000;
        server_name your_domain_or_IP;
    
        location / {
            proxy_pass http://localhost:8001;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
```
    
シンボリックリンク作成します。
    
```
sudo ln -s /etc/nginx/sites-available/my-fastapi /etc/nginx/sites-enabled/
```
    
Nginx再起動します。

```
sudo systemctl restart nginx
```
    
Nginxと通信するための内容でuvicornを立ちげます。
    
```
uvicorn main:app --host 0.0.0.0 --port 8001
```
    
**完了です。**

## 詰まったところ
ルータにフォワーディングの設定が必要になります。今回の作業とはあまり関係ありませんが、自宅のバッファロールータとChromeの相性が悪いようで、設定の反映がうまくいかず時間がかかりました。windowPCで作業していたのでEdgeに切り替えるとあっさりできました。
追記→ブラウザ依存の問題ではなくブラウザキャッシュの問題でした。

## 感想と今後
グローバルIPが切り替わるので、手動で対応するかDDNSで対応します。ポート空けっぱなしが怖いので多少お金かかってもどこかのタイミングでクラウドに移したいです。
今回の機能は複雑なやりとりではなかったですが、FASTAPIの設定が想像以上に簡単で驚きました。