フォネティックコードを調べるAPIを作る

<!-- フォネティックコードを調べるAPIを作る -->

こんにちは。Udonです。

最近、APIを自作してみようと考えていて、Flaskを使ってこれを実現することにしてみました。

題材は何にしようかな、ということで、覚えきれていなかったフォネティックコードを使うことにしました。

[NATOフォネティックコード - Wikipedia](https://ja.wikipedia.org/wiki/NATO%E3%83%95%E3%82%A9%E3%83%8D%E3%83%86%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B3%E3%83%BC%E3%83%89)

## APIの機能

フォネティックコードは、AからZまでのアルファベット各種に対応しています。

というわけで、クエリとしてアルファベットを渡すことで、それに対応するフォネティックコード及びその読み方をjson形式で返す、といった働きのものを作成することとしました。

## 作成手順

### 環境

APIの実現のためには、Flaskを使うことにしました。理由としては、自分がPythonに慣れているということと、元々使ってみたいと思いつつ手が出せていなかったということがあります。

というわけで、以下のような環境で作業を始めました。サービスのデプロイにはDockerを使うことにしました。Dockerコンテナ内でFlaskを動かすことで、環境を汚染せず安定して動作させます。また、Ubuntu上でPythonの外部ライブラリを用いる際、venvなどを気にする必要があったので、Dockerを使うことでこれを回避できると考えました。

- Flask 3.0.0
- Ubuntu 24.04
- Docker 24.0.5

### ディレクトリ構成

ディレクトリの構成は以下のようにしました。

```bash
.
├── app
│   ├── main.py
│   └── phonetic_codes.py
├── Dockerfile
├── docker-compose.yaml
└── requirements.txt
```

#### Dockerfile

ここには、Docker環境を構築するための情報を記述します。どんなイメージを取ってくるのかということと、そのイメージに対して何を行うのかということを記述します。

```Dockerfile
FROM python:3.10.5-alpine3.16
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
```

#### docker-compose.yaml

ここには、実際にDockerコンテナの中で行わせることを記述します。今回は、Flaskを動かすためのコマンドを記述します。また、ポートの設定も書いておきます。

`tty: true`とすることで、コンテナを作動させたまま放置することができます。

```yaml
version: '3.8'
services:
  app:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - ./app:/usr/src/app:rw
    environment:
      TZ: Asia/Tokyo
    command: ["python3", "main.py"]
    tty: true
```

#### requirements.txt

ここには、Flaskをはじめとする外部ライブラリの情報を記述します。

今回はAPIなので、Flaskとrequests、jsonfyを使います。

```requirements.txt
Flask == 3.0.0
requests == 2.31.0
jsonfy == 0.4
```

#### main.py

APIの核となるコードで、ここにはAPIのエンドポイントを記述します。

```python
from flask import Flask,request,jsonify
from phonetic_codes import codes,reads

app=Flask(__name__)

@app.route("/",methods=["GET"])
def get_codes():
    query=request.args.get("code",None,type=str)
    if not query:
        return "Hello! This is Phonetic-Code API!!"
    if query not in codes:
        return jsonify({"message":"Invalid query was received!!"}),400
    return jsonify({"code":codes[query],"read":reads[query]}),200

if __name__=="__main__":
    app.run(host="0.0.0.0", port=5000)
```

そこまで複雑な構成ではないです。今回はhttpのGETメソッドだけを使った構成にしているので、それに対応した処理のみを記述します。

`query`は受け取ったクエリとし、クエリがなかったり不正だったりする場合はエラーメッセージを返します。それ以外の場合は、フォネティックコードとその読み方をjson形式で返します。

サーバ外からアクセスを可能にするために、`app.run()`の引数に`host="0.0.0.0"`と`port=5000`を追加しています。

ポート番号は5000番にしていますが、これはFlaskのデフォルトのポート番号です。もし他のポート番号を使いたい場合は、`docker-compose.yaml`の`ports`の部分とともに変更してください。

#### phonetic_codes.py

ここには、フォネティックコードの情報を記述します。ただ辞書型のデータ構造が2つ並んでいるだけです。

```python
codes={
    "A":"Alpha",
    "B":"Blavo",
    # 中略
    "Y":"Yankee",
    "Z":"Zulu"
}
reads={
    "A":"アルファ",
    "B":"ブラボー",
    # 中略
    "Y":"ヤンキー",
    "Z":"ズールー"
}
```

受け取ったクエリを用いてこの辞書から情報を取り出し、それをjson形式で返す、というのが今回のAPIの機能です。

### 実行

それでは、実際にコンテナを立ち上げてみます。

```bash
$ sudo docker-compose build
$ sudo docker-compose up
```

これにより、`http://[サーバのIPアドレス]:5000`にアクセスすることで、APIを利用することができます。

たとえば、以下のような形式でクエリを渡すと、

```
http://[サーバのIPアドレス]:5000/?code=D
```

以下のような形式で答えが返ってきます。

```json
{
    "code":"Delta",
    "read":"デルタ"
}
```

もちろん、`curl`を使って叩いてあげても同じような結果が得られます。

## まとめ

Flaskを用いてAPIを作成し、Dockerを使って常設することができました。

Flaskを用いることで、結構簡単にAPIが作成できたので、良い勉強になりました。Flaskは拡張性の高いフレームワークなので、これからもいろいろ試してみたいと思います。

## 参考

[実践：はじめてのWebAPI設計 #Python - Qiita](https://qiita.com/kazuki_tachikawa/items/7dab01ac2ea08b85fb15)