HTTP ルーティング
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2024年05月07日(火)
Table of Contents
- ルーティング
- リクエストの分散
- リクエストの並列性の制限
- Common Runtime での dyno の接続動作
- Private Spaces での dyno の接続動作
- タイムアウト
- 同時接続
- リクエストのバッファリング
- 応答のバッファリング
- Heroku のヘッダー
- Heroku ルーターのログ形式
- キャッシング
- WebSocket
- gzip で圧縮された応答
- サポートされている HTTP メソッド
- Expect: 100-continue
- サポートされている HTTP のバージョン
- HTTP/1.1 対 HTTP/2
- HTTP の検証と制限
- プロトコルのアップグレード
- サポート対象外
- Common Runtime で使用可能な暗号スイート
Heroku プラットフォームでは、アプリのホスト名に送信された HTTP リクエストが自動的に Web dyno にルーティングされます。Common Runtime スタック上のすべてのアプリケーションのエントリポイントは、Web dyno への直接ルーティングパスを提供する herokuapp.com
ドメインです。
この記事では、ルーターがどのように動作するか、および HTTP 仕様への準拠状況について、詳細なリファレンスを示します。
この記事では、現在のルーターの HTTP ルーティングについてのみ説明します。HTTP/2 については、「Heroku Router 2.0 (パブリックベータ版)」および「Heroku Labs: Private および Shield Spaces 向け HTTP/2 (パブリックベータ版)」を参照してください。
ルーティング
インバウンドリクエストは、SSL ターミネーションを提供するロードバランサーによって受信されます。リクエストは、ここから一連のルータに直接渡されます。
ルーターは、アプリケーションの Web dyno の場所を判断し、これらの dyno のいずれかに HTTP リクエストを転送する役割を担います。
Heroku インフラストラクチャ経由でのエンドクライアントからアプリケーションへのリクエストの非難読化されたパスにより、チャンク化された応答、長いポーリング、WebSocket、非同期 Web サーバーを使用した 1 つの Web プロセスからの複数の応答の処理などの HTTP 1.1 の機能を完全にサポートできます。HTTP 1.0 との互換性も維持されます。
Heroku の HTTP/2 は現在、Common Runtime と Private Spaces 向けのパブリックベータ版で利用可能です。
リクエストの分散
ルーターは、ランダム選択アルゴリズムを使用して、Web dyno 間で HTTP リクエストのバランシングを行います。多数の dyno がある場合は、このアルゴリズムによって、選択を行うルーターと同じ AWS 可用性ゾーンに存在する dyno に対する選択に任意でバイアスがかけられる場合があります。
リクエストの並列性の制限
各ルーターでは、内部のアプリごとのリクエストカウンターが維持されます。Common Runtime では、ルーターでアプリごとの同時リクエスト数が制限されます。ただし、ルーター間での調整は行われないため、このリクエストの制限はルーターごとになります。各ルーターのリクエストカウンターの最大サイズは 200n です (n は、アプリで実行中の Web dyno の数)。特定のルーターのリクエストカウンターがいっぱいになると、そのルーターへのその後のリクエストは、すぐに H11 (バックログが深すぎます) の応答を返します。
Common Runtime での dyno の接続動作
Heroku が HTTP リクエストを受信すると、ルーターは、Common Runtime で実行中のランダムに選択された Web dyno への新しいアップストリーム TCP 接続を確立します。dyno が接続を拒否するか、5 秒後に接続を確立できない場合は、dyno を隔離します。そのルーターは最大 5 秒間、dyno にリクエストを転送しなくなります。隔離は、1 つのルーターにのみ適用されます。隔離されている dyno のリストは各ルーターで独自に管理されるため、ほかのルーターは、その dyno に接続を転送し続ける可能性があります。
接続が拒否されるかタイムアウトになると、リクエストを処理しているルーターは別の dyno で接続を再試行します。接続試行は最大 10 回まで行われますが、実行中の Web dyno が 10 個未満の場合は、試行回数は少なくなります。接続を確立できない場合、ルーターは「H19: Connection Timeout」 (H19: 接続タイムアウト) または「H21: Connection Refused」 (H21: 接続が拒否されました) のエラーを返します。
すべての dyno が隔離された場合、ルーターはインクリメンタルなバックオフを使用して最大 75 秒間、隔離されていない dyno の検索を再試行します。ルーターは隔離されていない dyno を見つけた場合、接続を確立しようとします。隔離されていない dyno を見つけられない場合、75 秒後にルーターは 503 で応答し、H99 エラーを返します。
接続を確立しようとする場合、リクエストの合計タイムアウトは 75 秒です。
Private Spaces での dyno の接続動作
Private Space の dyno は、専用のネットワークおよびルーティングレイヤーで実行され、プライベートネットワーク上で相互に通信します。Private Space のルーターは、許可されている一連の固定 IP アドレス上でアウトバウンド HTTP リクエストを受信します。
Common Runtime の Web dyno でのルーターの動作とは異なり、Private Space のルーターは、接続が拒否されるかタイムアウトになった場合に、ある Web dyno から別の Web dyno に HTTP リクエストの接続を転送しません。代わりに、30 秒後に接続がタイムアウトになり、H12 を返します。Private Space でのルーティング動作の詳細については、「Routing in Private Spaces」(Private Space でのルーティング) の記事を参照してください。
タイムアウト
dyno の接続が確立された後、HTTP リクエストの最初の 30 秒間の期間内に、Web プロセスが応答データ (完了済みの応答、またはプロセスがアクティブであることを示す一定量の応答データ) を返す必要があります。最初の 30 秒間の期間内に応答データを返さないプロセスについては、ログに H12 エラーが表示されます。
初回応答の後、(クライアントから、またはアプリのプロセスから) 送信されるバイトごとに繰り返しの 55 秒間の期間がリセットされます。この 55 秒間の期間中にデータが送信されないと、接続が切断され、H15 または H28 エラーがログに記録されます。
詳細は、「Request Timeout」(リクエストのタイムタウト) の記事を参照してください。
同時接続
herokuapp.com
のルーティングスタックでは、Web dyno への多数の同時接続が可能です。本番アプリについては、アプリの応答性を最大化するために、複数の同時接続が可能な内蔵 Web サーバーを常に選択する必要があります。長いポーリングのリクエストについても、同時接続を利用できます。
ほとんどすべての最新の Web フレームワークと内蔵可能な Web サーバーは、複数の同時接続をサポートしています。dyno でのリクエストの同時処理が可能な Web サーバーの例として、Unicorn (Ruby)、Goliath (Ruby)、Puma (JRuby)、Gunicorn (Python)、および Jetty (Java) があります。
リクエストのバッファリング
受信リクエストを処理するときに、ルーターはバッファを設定して、HTTP リクエスト行全体とリクエストヘッダーを受信します。リクエスト行とヘッダーのそれぞれに、「HTTP の検証と制限」で詳細に記載されている制限があります。content-length (コンテンツ長) が明確に定義されているリクエストの本体は、継続的に入力とフラッシュが繰り返される 1024 バイトのバッファーを使用して伝送されます。このサイズは、容量面で、リクエストの大半に対応できるサイズです。データが着信すると、ストリーミングされるリクエスト本体 (チャンクエンコーディング) が通過します。HTTP ヘッダー一式が受信されると、初めてリクエストの dyno へのディスパッチが開始されます。
結果として、それぞれのルーターがすべてのリクエストのヘッダーセクションをバッファリングし、Heroku の内部ネットワークの実行と同じ速さで dyno に配信します。リクエスト本体を読み込む必要があるまで、dyno は低速のクライアントから保護されます。リクエストの本体を低速で伝送するクライアントから保護する必要がある場合は、dyno で接続を終了してリクエストをドロップするタイミングを決定するために利用できるリクエストヘッダーを設定します。
応答のバッファリング
ルーターは、1 つの接続あたりの dyno からの応答に対して、1 MB のバッファを維持します。つまり、クライアントが応答を受信する速度が dyno に影響するまでに最大 1 MB のサイズの応答を送信できます。dyno が接続を終了しても、ルーターは応答のバッファーをクライアントに送信し続けます。1 MB のバッファーサイズより大きい応答の転送レートは、クライアントがデータを受信できる速度に制限されます。
Heroku のヘッダー
HTTP 仕様のとおり、すべてのヘッダーは大文字と小文字が区別されるものと見なされます。X-Forwarded-For
、X-Forwarded-By
、X-Forwarded-Proto
、X-Forwarded-Host
の各ヘッダーは、既存のフィールドが追加された順番を識別することができないため、セキュリティ上の理由から信頼されません (Forwarded HTTP Extension)のとおり)。
X-Forwarded-For
: Heroku ルーターに接続しているクライアントの発信元の IP アドレスX-Forwarded-Proto
: HTTP リクエストの発信元のプロトコル (例: https)X-Forwarded-Port
: HTTP リクエストの発信元のポート (例: 443)X-Request-Start
: リクエストがルーターに受信されたときの UNIX タイムスタンプ (ミリ秒)X-Request-Id
: Heroku の HTTP リクエスト IDVia
: Heroku ルーターのコードネーム
ネットワークエラーのログ記録
Heroku はネットワークエラーのログ記録 (NEL) を経由して選択したユーザーのブラウザデータを収集します。NEL は、インシデントが顧客に悪影響を及ぼし始める前にアクションを実行するための詳細な情報を Heroku に提供します。NEL は W3C 標準 (ドラフト) であり、エンドユーザーのデータを使用して Web アプリケーションのパフォーマンス特性をリアルタイムで測定する方法を定義します。
Google Chrome や Microsoft Edge など、いくつかのブラウザがこの標準を実装しています。サーバー上では、情報を集約して接続とレイテンシのメトリクスを処理するエンドポイントにレポートを送信するようブラウザに指示するヘッダーで、HTTP 応答に注釈を付ける機能があります。Heroku は、Salesforce のプライバシーに関する声明に従って NEL を実施します。
Heroku は HTTP 応答に次のヘッダーを追加します。
NEL
: ネットワークリクエストのログ記録を設定するために使用されるヘッダーReport-To
: このフィールドは、ユーザーエージェントに起点のレポートエンドポイントを保存するように指示しますReporting-Endpoints
: リソースのレポート設定を構成するために使用されるエンドポイント
Heroku ルーターのログ形式
この記事では、現在のルーターの HTTP ルーティングについてのみ説明します。新しい Router 2.0 でのルーターのログ形式変更については、「Heroku Router 2.0 (パブリックベータ版)」を参照してください。
情報ログ
次の内容は、ログドレインに送信される情報です。
264 <158>1 2012-10-11T03:47:20+00:00 host heroku router - at=info method=GET path=/ host=example-app-1234567890ab.herokuapp.com request_id=8601b555-6a83-4c12-8269-97c8e32cdb22 fwd="204.204.204.204" dyno=web.1 connect=1ms service=18ms status=200 bytes=13 tls_version=tls1.1 protocol=http
次の内容は、同じログ行を heroku logs
で表示した場合のものです。
2012-10-11T03:47:20+00:00 heroku[router]: at=info method=GET path=/ host=example-app-1234567890ab.herokuapp.com request_id=8601b555-6a83-4c12-8269-97c8e32cdb22 fwd="204.204.204.204" dyno=web.1 connect=1ms service=18ms status=200 bytes=13 tls_version=tls1.1 protocol=http
method
: HTTP リクエストのメソッドpath
: HTTP リクエストのパスとクエリ文字列host
: HTTP リクエストのHost
ヘッダーの値request_id
: Heroku の HTTP リクエスト IDfwd
: HTTP リクエストのX-Forwarded-For
ヘッダーの値dyno
: リクエストに対応した dyno の名前connect
: バックエンド Web プロセスへの接続の確立にかかった時間 (ミリ秒)service
: バックエンド Web プロセスとクライアントとの間のデータのプロキシにかかった時間 (ミリ秒)status
: HTTP 応答コードbytes
: バックエンド Web プロセスからクライアントに転送されたバイト数protocol
: リクエストのプロトコルを示しますtls_version
: 接続に使用された TLS バージョン。可能な値は ssl3.0、tls1.2、tls1.3、または unknown です。注意: これは Private Spaces の場合のみです。
エラーログ
次の内容は、ログドレインに送信される情報です。
277 <158>1 2012-10-11T03:47:20+00:00 host heroku router - at=error code=H12 desc="Request timeout" method=GET path=/ host=example-app-1234567890ab.herokuapp.com request_id=8601b555-6a83-4c12-8269-97c8e32cdb22 fwd="204.204.204.204" dyno=web.1 connect= service=30000ms status=503 bytes=0 protocol=http
次の内容は、同じログ行を heroku logs
で表示した場合のものです。
2012-10-11T03:47:20+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path=/ host=example-app-1234567890ab.herokuapp.com request_id=8601b555-6a83-4c12-8269-97c8e32cdb22 fwd="204.204.204.204" dyno=web.1 connect= service=30000ms status=503 bytes=0 protocol=http
code
: Heroku のエラーコードdesc
: エラーの説明
キャッシング
大量の静的アセットに対応するアプリでは、HTTP キャッシングを利用すると、パフォーマンスを改善し、負荷を減らすことができます。
WebSocket
すべてのアプリケーションで WebSocket 機能がサポートされています。
gzip で圧縮された応答
Common Runtime のアプリへのリクエストは、nginx のように HTTP サーバー経由でプロキシされるのではなく、直接アプリケーションサーバーに対して行われるため、応答の圧縮はアプリケーション内で行う必要があります。
サポートされている HTTP メソッド
Heroku の HTTP スタックは、RFC で定義されていないものも含め、CONNECT を除くあらゆる HTTP メソッド (「動詞 (verb)」とも呼ばれる) をサポートしています。
よく使われるメソッドは、GET、POST、PUT、DELETE、HEAD、OPTIONS、PATCH などです。メソッド名の長さは 127 文字に制限されています。
Expect: 100-continue
HTTP プロトコルには、サービス全体を向上させるためにクライアントがサーバーと連携できるようにする内蔵のメカニズムがいくつかあります。このようなメカニズムの 1 つに、リクエストと一緒に送信できる Expect: 100-continue
ヘッダーがあります [1]。
このヘッダーと値は、DoS 攻撃の問題を防止したり、多少の最適化を可能にしたりするために、大量の HTTP リクエストを送信してもサーバーが安全に受け入れることができるかどうかを送信前に確認する必要がある場合に、親和性のあるクライアントによって使用されます。cURL HTTP クライアントは、このメカニズムを使用する最もよく知られているライブラリで、content-body (コンテンツ本体) が 1 KB を超える場合にこの処理を行います (文書化されていない動作)。
サーバーは、許可を求められた場合はいつでも、100 Continue
HTTP ステータスで応答できます。これにより、サーバーがリクエストを受け入れられる状態であることをクライアントに知らせ、クライアントに処理を続行するように伝えます。サーバーは、リクエストに対応できない場合、状況に合うほかの HTTP 応答 (負荷の処理を拒否する場合は 413 Request Entity Too Large
など) を返すことができ、
任意で、その後すぐに接続を終了することもできます。
そのため、2 台のクライアントとサーバー間で行われるメカニズムは、通常の呼び出しの場合、だいたい次のようになります。
[Client] [Server]
|-------- Partial Request -------->|
|<--------- 100 Continue ----------|
|--------- Request Body ---------->|
|<----------- Response ------------|
また、拒否されたリクエストの場合は、次のようになります。
[Client] [Server]
|-------- Partial Request -------->|
|<-- 413 Request Entity Too Large -|
ただし、すべてのサーバーとクライアントがそのメカニズムを認識できるとは限らないため、このメカニズムは弾力性を高める必要があります。そのため、クライアントは、サーバーが Expect: 100-Continue
ヘッダーを受け入れて引き受けることができるかどうか不明な場合、しばらく待った後で実際の本体を送信する必要があります。
[Client] [Server]
|-------- Partial Request -------->|
| |
| |
| |
|--------- Request Body ---------->|
|<----------- Response ------------|
デフォルトでは、多くの Web サーバーでは Expect: 100-continue
のメカニズムに対応していません。そのため、Heroku の HTTP ルーターは、ルーティング先のアプリケーションの代わりに自動的に 100 Continue
応答を挿入し、後でデータを転送します。
これにより、dyno の Web サーバーが関わっている限り、このメカニズムはほぼ全面的に無効になります。
100-Continue のサポートを有効にする
Heroku Labs 機能を通じて、(Heroku ベータプログラム)のメンバー向けに) エンドツーエンドの Continue がサポートされるようになりました。
$ heroku labs:enable http-end-to-end-continue
この拡張機能が有効になっている場合は、100-Continue 機能の一般的なフローが復元され、ルーターによって expect: 100-continue
ヘッダーとそれらに関連する 100 continue
応答が透過的に渡されます。
ただし、この機能には、指定する必要がある独自のコーナーケースと動作があります。
コーナーケース
この種類のリクエストに付随する可能性がある一連のコーナーケースがあります。
元の HTTP 1.1 RFC (RFC 2068)
では、100 Continue
部分応答を使用して、サーバーに「リクエスト全体が解析されていませんが続けてください。すぐには拒否しません」と伝えさせることができました。後の RFC (たとえば、RFC
2616) には Expect: 100-continue
のメカニズムが含まれており、前のセクションのテキストで定義されているメカニズムの一環として 100 Continue
部分応答を再び利用できるようになりました。
下位互換性を維持するために、サーバーは Expect
ヘッダーを受信していなくても 100 Continue
を送信できますが、そのようにしないことを強くお勧めします。
2 番目のコーナーケースとして、サーバーが直接本体データの受信と処理を開始した場合は、クライアントがそれを認識するため、サーバーは 100 Continue
応答を送信しない場合があります。
また、ヘッダーに 1 つ以上の値が含まれている可能性を考慮して、サーバーでは Expect
ヘッダーの解析時に注意する必要があります。
たとえば、サーバーが大きな本体を処理することを想定している場合は Expect: 100-continue, auth
を送信することができますが、その前に認証を求めます。技術的には、純粋にクライアントとサーバーのために定義される動作が含まれる Expect
ヘッダー内には、必要な数の値をいくつでも含めることができます。
その他の特別なケースとして、接続フローを管理するヘッダーが複数あるために予期しないやり取りが発生する場合があります。たとえば、次のような場合があります。
- クライアントリクエストに接続の Upgrade リクエスト (WebSocket の場合) と
Expect: 100-continue
ヘッダーの両方が含まれている場合。 - サーバーが
100 Continue
ステータスコードで応答するが、受信時に接続を切断する必要があるConnection: close
などのヘッダーも含まれている場合。
これらの動作は元の仕様では未定義のため、動作の一貫性を保つためには、Heroku ルーターでこのような動作に関する判断を行う必要があります。
プロキシの要件
Expect
ヘッダーはエンドツーエンドのヘッダー (クライアントとサーバーだけが注意を払う必要があり、ヘッダー内で任意の用語を使用できる理由を説明する) として定義されるにもかかわらず、100 Continue
メカニズム自体 (および一般的な Expect
の動作のサポート) は、プロキシとの調整を必要とし、ホップバイホップです。
RFC では、次のような特別な条件が追加されています。
- プロキシは、サーバーが処理できるかどうかを把握しているかに関係なく、ヘッダーを現状のまま渡す必要があります。
- ルーティング先サーバーの HTTP バージョンが 1.0 以下であることが判明している場合、プロキシは
417 Expectation Failed
ステータスでリクエストを拒否する必要がありますが、判明していない可能性があります。 - HTTP 1.0 (またはそれ以前) のクライアントは
Expect: 100-Continue
ヘッダーなしでリクエストを送信できますが、それでもサーバーは (RFC 2068) の一環として)100 Continue
HTTP コードを使用してリクエストに応答できます。その場合、プロキシはその応答を完全に取り除き、最終ステータスの中継を待つ必要があります。
Heroku Router 100-continue のサポート
Heroku ルーターは、未定義の動作や前述のコーナーケースに関して、一部、次のように独自の対応を行います。
100 Continue
は、クライアントが HTTP 1.0 (またはそれ以前) クライアントであり、リクエストにExpect: 100-continue
ヘッダーが含まれていない場合は取り除かれ、それ以外の場合はどんな状況でも転送されます。- リクエスト本体の送信を開始するために
100 Continue
応答は必要ありませんが、クライアントに応じて、(Heroku での接続に関する通常のアイドル状態のルールに違反せずに) 待ち時間を設けます。 - 自動的に
417 Expectation Failed
応答で応答し、Expect
ヘッダーに100 Continue
(大文字と小文字区別なし) 以外の値が含まれている場合は、dyno への接続を終了します。 - WebSocket のアップグレードが要求された場合は、現状のまま dyno に送信され、どの応答が届いても対応します。
100 Continue
ステータスによって WebSocket のアップグレードが無視され、(通常どおりに) コードが返される可能性があります。また、101 Switching Protocol
によってExpect
ヘッダーの動作が無視されます。HTTPbis Draft を順守するために、サーバーから100 Continue
を受信した後、101 Switching Protocol
が送信されるのを待つ点に留意してください。 100 Continue
のConnection: close
を無視し、最終応答の受信後にのみ、この処理に対応します。RFC で「現在のリクエスト / 応答が完了した後で」接続を終了する必要があること、また100
はターミナル (終了) ステータスではないことが規定されていることを考慮して、接続はターミナルステータスの受信後にのみ終了されます。ただし、Connection: close
は ホップバイホップのメカニズムのため、必ずしもクライアントへの接続を終了せず、リクエストを転送しない可能性があります。- RFC で規定されているヘッダーはないこと、また実装がシンプルになることを考慮して、
100 Continue
応答からすべてのヘッダーを取り除きます。 - サーバーから初回の
100 Continue
応答の後で100 Continue
が返された場合、5xx エラーコードを返します。無限の 1xx ストリームは、まだサポートされていません。 - 先行して、または事前に
100 Continue
が返されたかどうかに関係なく、ターミナルステータスコードの後でサーバーへの接続を終了します。dyno への接続のキープアライブは行われません。 - 先行して
100 Continue
が返されなかったターミナルステータスコードの後で、クライアントへの接続を終了します。 これにより、クライアントがリクエスト本体を送信しなくても、サーバーが次のリクエストを処理できるようになります。
その他のメカニズムにはプロトコルで現状どおりに従う必要があり、RFC の規定どおりにリクエストを転送する必要があります。
サポートされている HTTP のバージョン
普及している主要な HTTP バージョンは、HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2 の 4 つです。
Heroku ルーターでは、HTTP/1.0 と HTTP/1.1 のクライアントのみサポートしています。HTTP/0.9 以前は、サポートされていません。SPDY と HTTP/2 は、現時点ではサポートされていません。
Heroku ルーターの動作は、可能な限り HTTP/1.1 の仕様に従うものとします。ただし、HTTP/1.0 では、次のような特別な例外処理を行う必要があります。
- クライアントが HTTP/1.0 を使用しているかどうかにかかわらず、HTTP/1.1 を使用して Heroku ルーター自体をアドバタイズします。
- チャンク化された応答から通常の HTTP 応答への必要な変換を引き受けます。ギガバイトにおよぶ可能性があるデータを蓄積せずにこの処理を行うために、クライアントへの応答は、接続の切断で区切られます 4.(4.5 項 を参照してください)。
- クライアントがリクエストごとに接続を終了すること (キープアライブなし) を希望しているものと想定します。
- HTTP/1.0 クライアントは、明示的に
connection:keep-alive
ヘッダーを使用して リクエストを送信する可能性があります。1.0 ではキープアライブのメカニズムが定義されていない (アドホックだった) にも関わらず、現時点で Heroku ルーターでは、リクエストされた動作が HTTP/1.1 と同様であることを想定しています。
Heroku の HTTP/2 は現在、Common Runtime と Private Spaces 向けのパブリックベータ版で利用可能です。
HTTP/1.1 対 HTTP/2
HTTP/1.1 と HTTP/2 は、Web サーバーとブラウザ間におけるデータ通信を制御する Hypertext Transfer Protocol (ハイパーテキストトランスファープロトコル、HTTP) の 2 つのバージョンです。HTTP/2 は、多重化やヘッダー圧縮などの機能を導入してレイテンシを削減することで、HTTP 1.1 よりも大幅に高速化されています。
HTTP の検証と制限
リクエストの検証:
- チャンク化されたエンコーディングと content-length の両方がリクエストで提示されている場合は、チャンク化されたエンコーディングが優先されます。
- 複数の content-length フィールドが提示されていて、それらが同じ長さである場合は、1 つの content-length ヘッダーにマージされます。
- content-length ヘッダーに複数の値 (
content-length: 15,24
) が含まれているか、複数の値を持つ複数の content-length ヘッダーがリクエストに含まれている場合、リクエストはコード 400 で拒否されます。 - ヘッダーは、1 行あたり 8192 バイト (およびヘッダー名につき 1000 バイト) に制限されています。
- 混乱を避けるために、ホップバイホップヘッダーは取り除かれます。
- 最大で 1 リクエストあたり 1000 個のヘッダーを使用できます。
- HTTP リクエストのリクエスト行は 8192 バイトに制限されています。
- リクエスト行では、単一のスペースで動詞 (verb)、パス、および HTTP バージョン間を区切る必要があります。
応答の検証:
- 混乱を避けるために、ホップバイホップヘッダーは取り除かれます。
- ヘッダーは、1 行あたり 512 KB に制限されています。
- Cookie は、明示的に 8192 バイトに制限されています。これは、まれに大きな Cookie 値を受け入れる一般的な制限 (たとえば、CDN によって課せられた制限など) から保護するためです。そのような場合、開発者が誤って大きな Cookie を設定してしまう可能性があり、それがユーザーに戻されると、ユーザーには自分のリクエストがすべて拒否されたと表示されます。
- ステータス行 (
HTTP/1.1 200 OK
) の長さは、8192 バイトに制限されています。
応答で上記の制限に違反しているアプリケーションのリクエストは、「502 Bad Gateway (不正なゲートウェイ)」の応答で失敗し、H25 エラーがアプリケーションのログストリームに送信されます。応答で上記の制限に違反しているクライアントのリクエストは、「400 Bad Request (不正なリクエスト)」の応答で失敗します。
さらに、HTTP/1.1 のリクエストと応答はデフォルトで keep-alive
であることが想定されていますが、初回のリクエストに明示的に
ルーターから dyno への connection: close
ヘッダーが含まれていた場合、dyno は、特定の content-encoding も明示的な content-encoding も含めずに、接続の切断で区切られた応答を送信できます。
プロトコルのアップグレード
以前の Heroku ルーターでは HTTP プロトコルのアップグレードが WebSocket のみに制限されていましたが、新しいルーターではすべてのアップグレードが許可されます。
実装に関する主なポイントは、以下のとおりです。
- アップグレード可能な接続では、あらゆる HTTP 動詞を使用できます。
HEAD
HTTP 動詞は通常、回線経由での適切な応答の送信を要求しませんが (たとえば、content-length に関してなど)、HEAD
リクエストは明示的に101 Switching Protocols
応答と連携するようになります。アップグレードしない dyno は別のステータスコードを送信する必要があります。接続はアップグレードされません。
サポート対象外
- SPDY
- HTTP/2*
- IPv6
100-continue
以外のコンテンツを含んだExpect
ヘッダー (417 になります)- WEBDAV などの HTTP 拡張機能
- content-length またはチャンク化されたエンコーディングを含んだ HEAD、1xx、204、または 304 応答では、送信されることがない本体を中継するためのプロキシの試行は行われません
- CRLF (
\r\n
) 以外のヘッダー行末 - HTTP コンテンツのキャッシング
- dyno で実行している HTTP バージョンのサーバーのキャッシング
- 事前に割り当てられたアイドル接続の長時間待機。アイドル接続が終了するまでの限度は 1 分に設定されています。
Host
ヘッダーのない HTTP/1.0 リクエスト。リクエスト行で完全な URL が送信される場合も、サポート対象外です。- TCP ルーティング
Heroku の HTTP/2 は現在、Common Runtime と Private Spaces 向けのパブリックベータ版で利用可能です。
Common Runtime で使用可能な暗号スイート
デフォルトドメイン
すべてのデフォルトドメイン (*.herokuapp.com)
トラフィック用にサポートされている暗号は、次のとおりです。
TLS_ECDHE-ECDSA-AES128-GCM-SHA256
TLS_ECDHE-RSA-AES128-GCM-SHA256
TLS_ECDHE-ECDSA-AES128-SHA256
TLS_ECDHE-RSA-AES128-SHA256
TLS_ECDHE-ECDSA-AES128-SHA
TLS_ECDHE-RSA-AES128-SHA
TLS_ECDHE-ECDSA-AES256-GCM-SHA384
TLS_ECDHE-RSA-AES256-GCM-SHA384
TLS_ECDHE-ECDSA-AES256-SHA384
TLS_ECDHE-RSA-AES256-SHA384
TLS_ECDHE-RSA-AES256-SHA
TLS_ECDHE-ECDSA-AES256-SHA
TLS_AES128-GCM-SHA256
TLS_AES128-SHA256
TLS_AES128-SHA
TLS_AES256-GCM-SHA384
TLS_AES256-SHA256
TLS_AES256-SHA
カスタムドメイン
すべてのカスタムドメイントラフィック用にサポートされている暗号は、次のとおりです。
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256