400 Bad request - プレーン HTTP リクエストが HTTPS ポートに送信される

現在、Apigee Edge のドキュメントを表示しています。
Apigee X のドキュメントをご確認ください
情報

内容

クライアント アプリケーションが、メッセージ The plain HTTP request was sent to HTTPS port を含む HTTP 400 Bad Request レスポンスを受信します。

エラー メッセージ

クライアント アプリケーションは、次のレスポンス コードを受け取ります。

HTTP/1.1 400 Bad Request

その後に、以下の HTML エラーページが表示されます。

<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
</body>
</html>

考えられる原因

原因 説明 トラブルシューティングの実施対象
TLS で構成された仮想ホストへの HTTP リクエスト クライアントが TLS で構成された仮想ホストに HTTP リクエストを送信する Edge Public Cloud ユーザーと Private Cloud ユーザー
TLS で構成されたターゲット エンドポイントへの HTTP リクエスト ターゲット エンドポイントの TLS 対応のバックエンド サーバーに対して送信された HTTP リクエスト。 Edge Public Cloud ユーザーと Private Cloud ユーザー
ターゲット サーバーの設定が正しくない ターゲット サーバーはセキュアポート 443 で構成されていますが、SSL が有効になっていません。 Edge Public Cloud ユーザーと Private Cloud ユーザー

原因: TLS で構成された仮想ホストへの HTTP リクエスト

このエラーは、クライアントが Apigee の API に接続しようとしたときに、前述の仮想ホストが SSL を使用するように構成され、代わりに HTTP リクエストを受信する場合に発生します。

診断

この問題は Northbound エンドポイントで発生し、クライアント アプリケーションと Router 間のエントリ ポイントとのやり取りで API リクエストが失敗するため、これらのエラー メッセージは NGINX ルーターのアクセスログに記録されません。そのため、これらのリクエストは API Monitoring や Trace ツールなどのツールでキャプチャされません。

  1. API リクエストを検証し、セキュアポート 443 でのみリクエストを受け入れるように構成されたホスト エイリアスに HTTP リクエストを行っているかどうかを確認します。そのような要素がある場合は、それが問題の原因です。

    不適切な API リクエストの例:

    curl http://org-test.apigee.net:443/400-demo
    
    <html>
    <head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
    <body>
    <center><h1>400 Bad Request</h1></center>
    <center>The plain HTTP request was sent to HTTPS port</center>
    <hr><center>server</center>
    </body>
    </html>
    
  2. 上記のサンプル リクエストでは、HTTP リクエストがセキュアポート 443 でホスト エイリアス myorg-test.apigee.net に対して行われています。これが 400 Bad Request エラーの原因です。

解像度

クライアントが HTTPS ではなく HTTP を使用しているかどうかを確認し、以下に示すように正しいリクエストを行う必要があります。

API リクエストの例:

curl https://org-test.apigee.net:443/400-demo

or

curl https://org-test.apigee.net/400-demo
< HTTP/1.1 200 OK
< Date: Thu, 25 Feb 2021 13:01:43 GMT
< Content-Type: text/xml;charset=UTF-8
< Content-Length: 403
< Connection: keep-alive
< Server: gunicorn/19.9.0
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true

原因: TLS で構成されたターゲット エンドポイントへの HTTP リクエスト

このエラーは、API プロキシのターゲット エンドポイントにある TLS 対応のバックエンド サーバーへの HTTP リクエストが誤って構成されている場合に発生します。

診断

Trace ツールを使用してエラーを診断する手順は次のとおりです。

  1. 影響を受ける API プロキシの Apigee UI で、[Trace] を有効にします。
  2. API プロキシにリクエストを送信します。
  3. 400 レスポンス コードで失敗した API リクエストを 1 つ選択します。
  4. さまざまなフェーズを確認し、エラーが発生した場所を特定します。
  5. 通常、バックエンド サーバーから 400 エラー レスポンスが返されます。つまり、次のように「Response received from target server」フェーズに 400 エラー レスポンスが表示されます。

  6. トレースの AX(Analytics Data Recorded)アイコンをクリックして、リクエストが実行されたターゲット エンドポイントを特定します。

  7. target.url をメモします。これには、プロトコル、バックエンド サーバーのホスト エイリアス、場合によってはポート番号が含まれます。ターゲット URL に使用されるポートは 443 ですが、プロトコルは HTTP です。
  8. ターゲット エンドポイントの定義を確認して、構成を把握します。
  9. バックエンド サーバーのホストが安全であり、443 などの安全なポートでリッスンしていることを確認します。<URL> 要素で http としてプロトコルを使用している場合、それがこの問題の原因です。

    ターゲット エンドポイントの構成例:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <TargetEndpoint name="default">
        <Description/>
        <FaultRules/>
        <PreFlow name="PreFlow">
            <Request/>
            <Response/>
        </PreFlow>
        <PostFlow name="PostFlow">
            <Request/>
            <Response/>
        </PostFlow>
        <Flows/>
        <HTTPTargetConnection>
            <Properties/>
            <URL>http://somehost.org:443/get</URL>
        </HTTPTargetConnection>
    </TargetEndpoint>
    

    上記の例では、HTTP プロトコルを使用していますが、使用されているポートはセキュアポート 443 です。これにより、バックエンド サーバーは 400 Bad Request とエラー メッセージ The plain HTTP request was sent to HTTPS port で応答します。

解像度

  1. バックエンド サーバーがセキュア/TLS 対応の場合は、次の例に示すように、ターゲット エンドポイントの <URL> 要素で https としてプロトコルを使用するようにします。

    ターゲット エンドポイントの構成例:

    <HTTPTargetConnection>
        <Properties/>
        <URL>https://somehost.org:443/get</URL>
    </HTTPTargetConnection>
    
  2. バックエンド サーバーが安全ではない場合:

    • セキュア ポート番号は含めないでください(例: 443)。
    • バックエンド サーバーがセキュアでない標準のポートでリッスンする場合は、ポート番号を指定する必要はありません。
    • 他のセキュアでないポートを使用している場合は、ポート番号を指定します(例: 9080)。

    ターゲット エンドポイントの構成例:

    <HTTPTargetConnection>
        <Properties/>
        <URL>http://somehost.org/get</URL>
    </HTTPTargetConnection>
    
    or
    
    <HTTPTargetConnection>
        <Properties/>
        <URL>http://somehost.org:9080/get</URL>
    </HTTPTargetConnection>
    

原因: ターゲット サーバーの構成が正しくない

ターゲット サーバーが 443 などのセキュアなポートで構成されており、SSL を有効にしていない場合、Apigee Edge の Message Processor が、セキュアなターゲットまたは TLS に構成されたターゲット サーバーに HTTP リクエストを送信すると、この問題が発生します。

診断

Trace ツールを使用してエラーを診断する手順は次のとおりです。

  1. 影響を受ける API プロキシの Apigee UI で、[Trace] を有効にします。
  2. API プロキシにリクエストを送信します。
  3. 400 レスポンス コードで失敗した API リクエストを 1 つ選択します。
  4. さまざまなフェーズを確認し、エラーが発生した場所を特定します。
  5. 通常、バックエンド サーバーから 400 エラー レスポンスが返されます。 つまり、次のように「Response received from target server」フェーズに 400 エラー レスポンスが表示されます。

  6. トレースの AX(Analytics Data Recorded)アイコンをクリックして、リクエストが実行されたターゲット エンドポイントを特定します。

  7. target.name をメモします。これはターゲット エンドポイント名を表します。

    上のトレース ファイルの例では、target.namedefault です。これは、このリクエストに使用されるターゲット エンドポイントがデフォルトであることを示します。

  8. ターゲット エンドポイントの定義を確認して、構成を把握します。

    ターゲット エンドポイントの構成例:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <TargetEndpoint name="default">
        <Description/>
        <FaultRules/>
        <PreFlow name="PreFlow">
            <Request/>
            <Response/>
        </PreFlow>
        <PostFlow name="PostFlow">
            <Request/>
            <Response/>
        </PostFlow>
        <Flows/>
        <HTTPTargetConnection>
            <Properties/>
            <LoadBalancer>
            <Server name="faulty-target"/>
            </LoadBalancer>
        </HTTPTargetConnection>
    </TargetEndpoint>
    

    上記のターゲット エンドポイント構成の例は、faulty-target という名前のターゲット サーバーを使用していることを示しています。

  9. ターゲット サーバー名を取得したら、次のいずれかの方法でターゲット サーバーの構成を確認できます。

    • Edge UI
    • Management API

Edge UI

  1. [Apigee Edge] > [Admin] > [Environments] > [Target Servers] に移動します。
  2. API プロキシから識別された特定のターゲット サーバーを選択し、[ 編集] をクリックします。
  3. ターゲット サーバーに指定されたポートと SSL 情報を確認します。
  4. ターゲット サーバーがセキュアなポート(443 など)で構成されているにもかかわらず、SSL が有効になっていない場合、それがこの問題の原因です。

    上のスクリーンショットからわかるように、使用されているポートは 443 ですが、ターゲット サーバー構成のそのポートでは SSL が有効になっていません。これにより、Apigee Edge の Message Processor はセキュアポート 443 に HTTP リクエストを送信します。そのため、エラー 400 Bad Request とメッセージ The plain HTTP request was sent to HTTPS port が表示されます。

Management API

  1. Get target server API を実行して、以下に示すように特定のターゲット サーバー構成の詳細を取得します。

    Public Cloud ユーザー:

    curl -v 'https://api.enterprise.apigee.com/v1/organizations/ORG_NAME/environments/ENV_NAME>/targetservers/TARGET_SERVER_NAME' \
    -H "Content-Type:application/xml" \
    -H "Authorization:Bearer $TOKEN"
    

    Private Cloud ユーザー:

    curl -v 'http://MANAGEMENT_IP:8080/v1/organizations/ORG_NAME/environments/ENV_NAME/targetservers/TARGET_SERVER_NAME' \
    -H "Content-Type:application/xml" \
    -H "Authorization:Bearer $TOKEN"
    
  2. ターゲット サーバーに指定されたポートと SSL 情報を確認します。
  3. ターゲット サーバーがセキュアポート(443 など)で構成されているにもかかわらず、SSLInfo セクションが定義されていないか、有効になっていない場合、それがこの問題の原因です。

    ターゲット サーバーの構成例:

    {
      "host" : "somehost.org",
      "isEnabled" : true,
      "name" : "faulty-target",
      "port" : 443
    }
    

    上記のサンプル出力では、ターゲット接続に使用されるポートが 443 ですが、SSLInfo 構成ブロックがありません。

    これにより、Apigee Edge の Message Processor はセキュアポート 443 に HTTP リクエストを送信します。そのため、エラー 400 Bad Request とメッセージ The plain HTTP request was sent to HTTPS port が表示されます。

解像度

ターゲット サーバーが保護されているか TLS 構成されている場合は、特定のターゲット サーバーで SSL を有効にする必要があります。

これは、次のいずれかの方法で行うことができます。

  • Edge UI
  • Management API

Edge UI

  1. [Edge UI] > [Admin] > [Environments] > [Target Servers] でターゲット サーバーに移動します。
  2. ターゲット サーバーを選択し、[ Edit] をクリックします。
  3. ターゲット サーバーが安全で、443 などのポートを使用している場合は、SSL オプションの横にあるチェックボックスをオンにして SSL を有効にします。
  4. トラストストア暗号プロトコルを構成します。(必要な場合のみ)

Management API

ターゲット サーバーの構成を更新するの説明に従って、管理 API を使用してターゲット サーバーを構成します。

診断情報の収集が必要な場合

上記の手順でも問題が解決しない場合は、次の診断情報を収集して Apigee Edge サポートに連絡してください。

  1. Public Cloud ユーザーの場合は、次の情報を入力します。
    • 組織の名前
    • 環境名
    • API プロキシの名前
    • 完全な curl コマンドでエラーを再現する
    • Trace ツールの出力(失敗したリクエストをキャプチャできた場合)
  2. Private Cloud ユーザーの場合は、次の情報を入力します。
    • 確認された完全なエラー メッセージ
    • 環境名
    • API プロキシ バンドル
    • ターゲット サーバーの定義(エンドポイントでターゲット サーバーを使用している場合)
    • Trace ツールの出力(失敗したリクエストをキャプチャできた場合)