0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

黄昏酒場スコアボード作成③〜バックエンド開発環境整備とAPI定義

Last updated at Posted at 2025-04-09

はじめに

これはの続きです。

バックエンド開発環境の作成

バックエンドはfastapiで動かす。fastapiはpythonで書くものなのでライブラリ関連は pip というPythonパッケージ管理ツールを使用して入れる。
これはDockerfileで CMD コマンドを使用して pip install -r requirements.txt と書いておき、母艦で requirements.txt に使用したいライブラリ一覧を記述し、 CMD コマンドの前に COPY コマンドを書いて母艦からコンテナに requirements.txt をコピーするようにして置けばDockerイメージをビルドする際に自動的に使用するライブラリが入ることになる。

しかしこのままだとVSCodeで編集する際に requirements.txt を記述したライブラリを使用しようとしたときに性的解析ツールが『そんなライブラリは知らん!!』とキレてくる。
何故Dockerfileに書いたのにVSCode上で怒られるかというと、あくまでコンテナ上にライブラリをインストールさせるようにしただけで、あくまでVSCodeで編集するのは母艦のpythonだからである。母艦にはライブラリを pip install していないので当然VSCode上の静的解析ツールはライブラリを認識しない。

脳筋であれば母艦上で pip install させれば解決することができるが、母艦の環境を汚すのは後々別のコンテナでホストを作成しようとしたときにライブラリが干渉する可能性がありダルい。
そこでpyenvというものを使用する。また、pyenv-installerというものを使用すればpyenvインストール時にpyenv-virtualenvというものも一緒に付いてきて、project毎、さらにはディレクトリ毎にpythonの環境を分けることができて便利である。

APIの定義

fastapiはHTTPリクエストのエンドポイントを定義することができる。
ざっくりHTTPについて説明すると Hyper Text Transfer Protocol の略で、サーバとブラウザ間でテキストベースに通信するための各コンピュータ間のお約束事(プロトコル)である。
HTTPには代表的には以下4種のメソッドがある。

  • GET
    • 単にサーバから情報を得る
  • POST
    • サーバに情報を送信する
  • PUT
    • サーバにある情報を更新する(正直 POST と区別がつかない)
  • DELETE
    • サーバにある情報を削除する

旧ロイヤルフレアでは、クライアントはcgiに対してリプレイをPOSTしたり削除パスワードを使用してDELETEし、それに対してcgiはhtmlファイルを生成して、記録を見たい人はcgiが作成したHTMLファイルをGETすることによって実現していた。
しかし今回はフロントエンドによってウェブページを動的に生成するものとした。よってクライアント側にはフロントエンドサーバから与えられたJavaScriptによる画面生成環境があり、JavaScriptに対してHTMLではなくJavaScriptが解釈できるようなフォーマットのテキストデータを送るだけで良くなり、画面生成の責任はない。
ここでフロントエンドの定義するJavaScriptがバックエンドに通信する出入口、及びそこから入出力されるデータを定義する必要が出てくる。このような出入り口をAPI (Application Programmable Interface)と呼ぶ。
今回のAPIは以下のように定義した。

  • GET /replays/sort={AA}&order={BB}&offset={CC}&limit={DD}
    • リプレイの一覧を取得する
    • sort以降のパラメータで取得できる情報を調整できる
    • もしかしたらデプロイまでに変えるかも
  • GET /replays/{replay_id}
    • replay_id に相当するリプレイ1件のメタデータを取得する
    • 今回は使用しないが便宜上作成する
    • 誰かが自分のページをもとに便利アプリ作りたければ使ってください
  • GET /replays/{replay_id}/file
    • replay_id に相当するリプレイファイルをダウンロードする
  • POST /replays
    • ユーザ名や投稿コメント、及び削除パスワードとともにリプレイをアップロードする
  • DELETE /replays/{replay_id}
    • 削除パスワードとともにリクエストすると replay_id に相当するリプレイを削除できる
  • GET /cocktail GET /wine GET /sake GET /beer GET /alcohol
    • /teapotというエンドポイントにリダイレクトする
  • GET /teapot
    • RFC2324に従って 418 I'm a teapot エラーを返す

ここまでで出入り口について定義できたが入出力されるデータフォーマットについて定義しなければならない。
特にHTTPはあくまでテキスト送受信の約束事なので通常であればリプレイファイルのようなバイナリファイルを送受信することはできない
そこでMIMEというものがRFC2045等で定義されており、これでテキスト送受信という建前を保ったままバイナリファイル等を送受信することができる。
MIMEで送れるフォーマットはIANAという組織で管理されており、 application/form-data や、 application/json 等がある。
jsonはキーバリューのデータ型で非常に扱いやすい。よって基本的に入出力はjsonで定義したがここで問題が起きた。
jsonのバリューにバイナリは入れられない1ので POST /replays でjsonが使えない。
そこで全てのエンドポイントで入力を揃えるためにform-dataの方を使おうとしたが今度は DELETE /replays/{replay_id} にてform-data形式でパスワードを送信することができない。
というのもform-dataはHTTPが定義された初期からあり、HTTPのできた当初は『DELETEはあくまでリソースの削除であるから、サーバに送信するデータはない』と考えていたようで、form-dataの送信は禁止されているそう。
そこで一応ギリセーフである application/json でDELETE時のパスワードを送信することにした。

GET /alcohol などのエンドポイントは『黄昏酒場のスコアボードだし、お酒をGETリクエストしたらくれるのか?』と思わせて実はサーバ自体がティーポットで出来ているためお酒を渡すことは出来ないというエラーである2。リターナー3で我慢しろ。

次回

作る環境が出来、エンドポイントも定義できたので内部を実装していく。

  1. 文字列へBase64エンコードすれば入れることも技術的には可能だがそれやってる暇あったら application/form-data を使った方が良い。

  2. HTTP応答の 418 I'm a teapot は1998年のエイプリルフールに発表されたRFC2324にて定義された、サーバにコーヒーを入れてもらうためのプロトコルである HTCPCP ( Hyper Text Coffee Pot Control Protocol )で制定されたエラー応答である。
    このエラー応答は本来、サーバにコーヒーを入れてもらうように頼んだところ実はサーバはティーポットだったのでコーヒーは注げないというエラーである。
    しかし今回はお酒に関するサービスを提供するサーバなので、コーヒーの部分をお酒に変えて実装した。RFC違反とみなされてもしょうがないがそもそも HTCPCP はなんちゃってプロトコルだから許してくれ。

  3. 紅茶のお酒。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?