【実務・中級編】HTTPステータスコード505(HTTP Version Not Supported)の発生条件 – HTTPプロトコル・通信規格実践ガイド

505 HTTP Version Not Supported:その「断絶」はどこで起きているのか?

ネットワークの現場で「505 HTTP Version Not Supported」というエラーを目にすることは、現代のWeb開発において決して多くはありません。しかし、だからこそこのエラーに遭遇したとき、多くのエンジニアは困惑します。「なぜ、今さらプロトコルのバージョンで弾かれるのか?」と。

今日は、この一見古臭い、しかし本質的なエラーについて、プロトコルの深淵から紐解いていこうと思います。

—

505エラーの正体:通信の「握手」が成立しない瞬間

HTTPステータスコード 505 は、サーバーがリクエストで使用されたHTTPプロトコルのメジャーバージョンをサポートしていない、あるいはサポートを拒否したことを示します。

RFC 7231の定義によれば、サーバーはリクエストメッセージの開始行(Start Line)にあるバージョン情報を確認し、自らが対応していないと判断した場合、即座に505を返すべきとされています。これは単なる設定ミスではなく、「クライアントとサーバー間の言語が致命的に噛み合っていない」という宣告です。

発生する典型的なシナリオ

1. レガシーなインフラへのHTTP/2リクエスト: フロントエンドやリバースプロキシが HTTP/2 で通信しようとしているのに、バックエンドのアプリケーションサーバーが HTTP/1.1 までしか理解できない場合。
2. プロトコル・ダウングレードの失敗: セキュリティ要件により古いプロトコルを無効化した後、キャッシュや古いクライアントが過去のバージョンで接続を試みる場合。
3. 不適切なプロキシ/ゲートウェイの介在: 中継する中間のミドルウェアが、クライアントのバージョンをバックエンドに適切に変換・転送できず、生のリクエストをそのまま投げてしまった場合。

—

実践:505を意図的に再現し、通信を可視化する

理論を理解するには、まず「壊してみる」のが一番です。`curl` を使って、あえてサーバーが解釈不能なバージョン(例えば存在しないHTTP/3.0など)を送りつけてみましょう。

意図的に非対応のプロトコルバージョンを指定してリクエストを送る
–http3 は環境によりますが、サーバーがサポートしていないバージョンを
強制的に指定することでサーバーの拒絶を誘発します
curl -I –http3 https://example.com/api/v1/resource

もしサーバーが HTTP/1.1 しか喋れない環境であれば、レスポンスヘッダーには以下のように刻まれます。

HTTP/1.1 505 HTTP Version Not Supported
Date: Wed, 25 Oct 2023 10:00:00 GMT
Server: Apache/2.4.41 (Ubuntu)
Connection: close

サーバーは「そのバージョンでは会話できない」と即座に切断する

—

トラブルシューティングの定石:現場でどう切り分けるか

もしあなたがインフラエンジニアとしてこのエラーに直面したら、以下の手順で「どこで断絶しているか」を特定してください。

1. クライアントとサーバーの間の「翻訳者」を疑う

多くの場合、エラーはバックエンドサーバーではなく、手前のNginxやAWS ALB(Application Load Balancer)といったプロキシ層で発生します。Nginxの設定を確認しましょう。

nginx.conf の例
server {
listen 443 ssl http2; # HTTP/2 を有効化

location / {
# ここでバックエンドにプロキシする際、バージョンが維持されているか確認
proxy_pass http://backend_server;
proxy_http_version 1.1; # バックエンドが HTTP/1.1 なら必須
proxy_set_header Connection “”; # Keep-Alive を維持
}
}

2. Python (requests) での検証用スクリプト

トラブルの切り分けには、あえて生のリクエストを送るスクリプトを書くのが有効です。

import http.client

HTTP/1.1 よりも古いプロトコルをあえて指定するテスト
conn = http.client.HTTPConnection(“your-api-server.com”)
RFC的には HTTP/0.9 は非常に特殊な挙動をするため、
サーバー側で拒否設定されているかをテストできる
conn.request(“GET”, “/”, version=”HTTP/0.9″)
response = conn.getresponse()

print(f”Status: {response.status}”)
print(f”Reason: {response.reason}”)

—

エンジニアへの助言:プロトコルネゴシエーションの限界

HTTP/1.1 から HTTP/2、そして HTTP/3 (QUIC) へと進化する過程で、私たちは「いかに速く、効率的に通信するか」ばかりを追い求めてきました。しかし、プロトコルネゴシエーション(ALPNなど)は万能ではありません。

505 エラーは、「最新の技術スタックとレガシーな資産の境界線」で発生するアラートです。

  • API設計者へ: クライアントがどのバージョンで接続してきてもいいように、ゲートウェイ側でプロトコル変換を確実に行うこと。
  • 運用担当者へ: サーバーのアップデート時に、旧プロトコルのサポートを無効化する際は、クライアントの接続ログを必ず事前に確認すること。

「動いているから大丈夫」ではなく、「どのプロトコルで会話しているか」を常に意識する。その視点こそが、複雑なマイクロサービスアーキテクチャを支える確かな基盤となります。

もし次に 505 に出会ったら、それは「新しい世界へ踏み出そうとして、古い扉に弾かれた」という合図です。焦らず、プロキシのログを追いかけ、接続の握手を一つずつ解き明かしてください。それが、熟練したエンジニアの流儀です。

コメント

タイトルとURLをコピーしました