なぜ「GETでDBを更新してはいけないのか」――HTTP/1.1が定義する「安全」と「冪等」の深淵
ネットワークエンジニアとして現場に立っていると、若手から「GETリクエストでパラメータを送ってデータを削除したいのですが、何が問題なんですか?」という質問を受けることがあります。
ブラウザのアドレスバーにURLを叩けば動く。確かにその場は動くでしょう。しかし、HTTPというプロトコルが数十年かけて磨き上げてきた「意味論(セマンティクス)」を無視した実装は、いつか必ず大規模な障害という形で牙を剥きます。
今回は、HTTP/1.1の根幹をなす「安全(Safe)」と「冪等(Idempotent)」という概念について、RFC 7231の精神を紐解きながら、実務的な視点で解説します。
—
1. 「安全」と「冪等」の定義を正しく理解する
HTTP/1.1におけるメソッドの性質は、クライアントとサーバー間の「暗黙の契約」です。ここを勘違いすると、キャッシュやプロキシの挙動で泣きを見ることになります。
安全(Safe Methods)
定義: サーバーの状態を一切変更しないこと。
GETやHEADリクエストは、サーバー側のリソースに対して副作用(DBの更新、ログ以外の追記など)を与えてはいけません。
冪等(Idempotent Methods)
定義: 何回繰り返しても、サーバー側の状態が「初回実行時と同じ結果」になること。
例えば、`DELETE /users/1` は、1回目は削除されますが、2回目以降は「もう存在しない」という結果を返します。結果(リソースの状態)が累積的に変化しないため、冪等であると言えます。
なぜGETが重要なのか?
GETは「安全」かつ「冪等」である必要があります。この「安全」という保証があるからこそ、ブラウザやCDNは「何度リクエストしてもサーバーに影響を与えないなら、キャッシュして再利用してもいいよね」と判断できるのです。
—
2. なぜGETでの状態変更が「事故」を招くのか
もしあなたが `GET /delete_user?id=123` というAPIを作ったとします。Webクローラーやブラウザのプリフェッチ機能、あるいは社内の監視ツールがそのURLを巡回し始めたらどうなるでしょうか?
- 無意識の破壊: クローラーがページをインデックスするたびに、ユーザーデータが次々と削除されます。
- キャッシュの誤爆: CDNがGETレスポンスをキャッシュしていた場合、本来実行されるべきタイミングで処理がスキップされるか、あるいはキャッシュが破棄された瞬間に意図しないタイミングでリクエストが飛ぶという、デバッグ不能なバグを生みます。
—
3. 実践:正しいHTTPメソッドの使い分け
では、実務でどのように設計すべきか。Pythonの`requests`を用いたシミュレーションで確認しましょう。
import requests
良い例: GETは情報を取得するだけ
サーバー側は副作用を発生させない実装にする
def get_user_info(user_id):
url = f”https://api.example.com/users/{user_id}”
response = requests.get(url)
return response.json()
悪い例: GETで更新・削除を行っている(絶対NG)
監視ツールがこのURLを叩くと、意図せずユーザーが消える
def delete_user_wrong(user_id):
# こんなコードは書いてはいけない!
requests.get(f”https://api.example.com/delete?id={user_id}”)
良い例: 状態変更にはPOSTやDELETEを使う
これらは「安全」ではないため、キャッシュは適用されず意図した処理が行われる
def delete_user_right(user_id):
url = f”https://api.example.com/users/{user_id}”
response = requests.delete(url)
return response.status_code
—
4. インフラ屋の視点:デバッグと運用Tips
トラブルシューティングの際、パケットキャプチャやログを見るときに注目すべきポイントがあります。
curlでの疎通確認
API開発中にメソッドの挙動を確認する際は、`-v` (verbose) オプションでヘッダーを確認してください。
冪等性を確認する際は、連続して叩いてみる
curl -v -X GET “https://api.example.com/status”
レスポンスのCache-ControlやETagヘッダーを確認
GETならキャッシュが効きやすいが、POST/DELETEなら通常はキャッシュされない
ログ解析での違和感
サーバーログを見ていて、`GET` リクエストに対して `201 Created` や `204 No Content` が頻発している場合は「赤信号」です。本来GETは `200 OK` を返すのが定石です。GETリクエストで「処理が完了した」というステータスを返しているなら、それは設計の敗北と言っていいでしょう。
—
まとめ:プロフェッショナルとして
HTTPメソッドの使い分けは、単なる「作法」ではなく、インターネットという巨大なネットワークを安定して動かすためのプロトコル上の制約です。
- GETは「参照」のみ。
- 副作用を伴うなら「POST/PUT/DELETE」を使う。
- 「安全」であるからこそ、ネットワーク機器(CDN/Proxy)は最適化できる。
私たちが書く1行のコードが、世界中のどこかのサーバーやキャッシュサーバーを経由して届きます。その裏側にあるプロトコルの美学を理解し、堅牢なシステムを構築していきましょう。
もし現場で「GETで更新しちゃえば楽じゃん」という誘惑に駆られたら、この記事を思い出してください。楽をした分、後で必ず倍以上のコストを払うことになりますから。
コメント