400 Bad Request - DecompressionFailureAtRequest

您目前查看的是 Apigee Edge 說明文件。
前往 Apigee X 說明文件
info

問題

用戶端應用程式會收到 HTTP 狀態碼 400 Bad Request 和錯誤碼 messaging.adaptors.http.flow.DecompressionFailureAtRequest ,做為 API 呼叫的回應。

錯誤訊息

用戶端應用程式會取得下列回應代碼:

HTTP/1.1 400 Bad Request

此外,您可能會看到類似下方的錯誤訊息:

{
   "fault":{
      "faultstring":"Decompression failure at request",
      "detail":{
         "errorcode":"messaging.adaptors.http.flow.DecompressionFailureAtRequest"
      }
   }
}

可能原因

只有在下列情況下才會發生這個錯誤:

  • HTTP 要求標頭 Content-Encoding 中指定的編碼有效,且 Apigee Edge 支援該編碼
  • BUT

  • 用戶端在 HTTP 要求中傳送的酬載格式,與 Content-Encoding 標頭中指定的編碼格式不符。

這是因為酬載格式與 Content-Encoding 標頭中指定的編碼格式不同,因此 Apigee Edge 無法使用指定的編碼解碼酬載。

以下列舉幾個支援的 Content-Encoding值,以及 Apigee Edge 在這些情況下預期的酬載格式:

情境 Content-Encoding 預期酬載格式
單一編碼 gzip

Unix gzip 格式。

請參閱 RFC1952 GZIP 格式

單一編碼 deflate

這個格式使用 zlib 結構,並採用 Deflate 壓縮演算法。

請參閱 RFC1950 RFC1951.

多重編碼

多重編碼

舉例來說,如果編碼作業執行兩次,則可能為:

  • gzip、deflate
  • gzip、gzip
  • deflate、gzip
  • deflate、deflate
系統會按照標頭中顯示的順序,對酬載套用多種編碼。

這項錯誤的可能原因如下:

原因 說明 適用於以下裝置的疑難排解說明
要求酬載格式與 Content-Encoding 標頭中指定的編碼方式不符 用戶端傳送的要求酬載格式未經過編碼,或與 Content-Encoding 標頭中指定的編碼不符。 Edge 公有和私有雲使用者

常見的診斷步驟

請使用下列其中一種工具/技術診斷這項錯誤:

API Monitoring

如要使用 API 監控功能診斷錯誤,請按照下列步驟操作:

  1. 以具備 適當角色的使用者身分登入 Apigee Edge UI。
  2. 切換至要調查問題的機構。

  3. 依序前往「Analyze」>「API Monitoring」>「Investigate」頁面。
  4. 選取您觀察到錯誤的特定時間範圍。
  5. 確認「Proxy」篩選器已設為「All」
  6. 繪製「錯誤代碼」與「時間」的關係圖。
  7. 選取含有故障代碼 messaging.adaptors.http.flow.DecompressionFailureAtRequest 的儲存格,如下所示:

    ( 查看較大圖片)

  8. 故障代碼資訊 messaging.adaptors.http.flow.DecompressionFailureAtRequest會顯示如下:

    ( 查看較大圖片)

  9. 按一下「查看記錄」,然後展開發生 400 錯誤的資料列。

    ( 查看較大圖片)

  10. 在「記錄」視窗中,記下下列詳細資料:
    • 狀態碼: 400
    • 錯誤來源: proxy
    • 故障代碼: messaging.adaptors.http.flow.DecompressionFailureAtRequest
  11. 如果「Fault Source」的值為 proxy,表示要求酬載格式與 Content-Encoding 標頭中指定的 支援編碼不符。

追蹤工具

如要使用「追蹤」工具診斷錯誤,請按照下列步驟操作:

  1. 啟用追蹤工作階段 和下列任一項目:
    1. 等待發生 400 Bad Request 錯誤,或
    2. 如果可以重現問題,請發出 API 呼叫並重現問題。400 Bad Request
  2. 確認已啟用「顯示所有流程資訊」

  3. 選取其中一個失敗的要求,然後檢查追蹤記錄。
  4. 瀏覽追蹤記錄的不同階段,找出發生失敗的位置。
  5. 通常在「Request Received from Client」(收到用戶端要求) 階段之後,您就會在流程中發現錯誤,如下所示:

    ( 查看較大圖片)

  6. 請注意追蹤記錄中屬性的值:

    • 錯誤: Decompression failure at request
    • error.classcom.apigee.rest.framework.BadRequestException
    • error.cause: Not in GZIP format

    error.cause 指出要求酬載並非 GZIP 格式。 也就是說,Apigee Edge 預期要求酬載採用 GZIP 格式,因為 Content-Encoding 標頭中已指定該格式。

  7. 判斷要求標頭 Content-Encoding 的值。 為此,請前往「Request Received from Client」階段,如下所示:

    ( 查看較大圖片)

    請注意,要求標頭 Content-Encoding 的值確實是 gzip

    上述範例追蹤記錄顯示,要求標頭中指定的編碼為 Content-Encodinggzip,但要求酬載並非 GZIP 格式。因此,Apigee 無法使用 gzip 解壓縮酬載,並會傳回 Decompression failure at request 錯誤。

  8. 請注意 Apigee Edge 傳回的狀態碼和錯誤訊息,方法是前往

    追蹤記錄中的「Response Sent to Client」階段,如下所示:

    ( 查看較大圖片)

    請注意追蹤記錄中的下列詳細資料:

    • 狀態碼: 400 Bad Request
    • 錯誤內容: {"fault":{"faultstring":"Decompression failure at request","detail":{"errorcode":"messaging.adaptors.http.flow.DecompressionFailureAtRequest"}}}
  9. 前往追蹤記錄中的「AX」(記錄的 Analytics 資料) 階段,然後按一下該階段。AX

  10. 向下捲動至「Phase Details」(階段詳細資料) 和「Error Headers」(錯誤標頭) 專區,然後判斷 X-Apigee-fault-codeX-Apigee-fault-source 的值,如下所示:

    ( 查看較大圖片)

  11. 您會看到 X-Apigee-fault-codeX-Apigee-fault-source 的值為 messaging.adaptors.http.flow.DecompressionFailureAtRequestpolicy,表示要求酬載格式與 Content-Encoding 標頭中指定的編碼不符。
    回應標頭
    X-Apigee-fault-code messaging.adaptors.http.flow.DecompressionFailureAtRequest
    X-Apigee-fault-source policy

NGINX

如要使用 NGINX 存取記錄診斷錯誤,請按照下列步驟操作:

  1. 如果您是私有雲使用者,可以透過 NGINX 存取記錄判斷 HTTP 400 錯誤的相關金鑰資訊。
  2. 檢查 NGINX 存取記錄:

    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

    說明: ORGENVPORT# 會替換為實際值。

  3. 搜尋特定時間範圍內是否有任何400錯誤 (如果問題發生在過去),或是否有任何要求仍400失敗。
  4. 如果發現任何 400 錯誤,且 X-Apigee-fault-codemessaging.adaptors.http.flow.DecompressionFailureAtRequest 的值相符,請判斷 X-Apigee-fault-source 的值。

    NGINX 存取記錄檔中的 400 錯誤範例:

    上述 NGINX 存取記錄檔的範例項目具有下列 X-Apigee-fault-codeX-Apigee-fault-source 值:

    回應標頭
    X-Apigee-fault-code messaging.adaptors.http.flow.DecompressionFailureAtRequest
    X-Apigee-fault-source policy

原因:要求酬載格式與 Content-Encoding 標頭中指定的編碼方式不符

根據預設,如果要求標頭 Content-Encoding 包含有效且 支援的編碼,Apigee Edge 一律會解壓縮酬載。因此,要求酬載的格式應與要求標頭 Content-Encoding 中指定的編碼方式相符。如果不相符,就會收到這項錯誤訊息。

診斷

  1. 使用 API 監控、追蹤工具或 NGINX 存取記錄,判斷觀察到的錯誤的錯誤代碼錯誤來源,如常見診斷步驟所述。
  2. 如果「錯誤代碼」messaging.adaptors.http.flow.DecompressionFailureAtRequest,且「錯誤來源」的值為 policyproxy,表示用戶端應用程式傳送的要求含有與要求標頭 Content-Encoding 中指定的 支援編碼不符的酬載。
  3. 您可以使用下列其中一種方法,在 HTTP 要求中判斷不符情形:

    錯誤訊息

    如何使用錯誤訊息進行驗證:

    1. 如果您可以存取 Apigee Edge 傳送的完整錯誤訊息,請參閱 faultstring

      錯誤訊息範例:

      "faultstring":"Decompression failure at request"
    2. 在上述錯誤訊息中,系統會顯示 "Decompression failure at request",這表示系統無法使用 Content-Encoding 標頭中指定的編碼,解壓縮要求

    追蹤記錄

    如要使用追蹤驗證,請按照下列步驟操作:

    1. 使用「追蹤」,判斷要求標頭 Content-Encoding 的值和 error.cause 屬性,如「常見診斷步驟」一文所述。
    2. 範例追蹤記錄中的值如下:

      • Content-Encoding: gzip
      • error.cause: Not in GZIP format

      要求標頭 Content-Encoding 中的值為 gzip,但要求酬載並非 GZIP 格式 (如 error.cause 所示)。因此,Apigee Edge 會傳回 400 Bad Request 和錯誤代碼 messaging.adaptors.http.flow.DecompressionFailureAtRequest

    實際要求

    如要使用實際要求進行驗證,請按照下列步驟操作:

    如果您可以存取用戶端應用程式發出的實際要求,請執行下列步驟:

    1. 判斷傳遞至要求標頭 Content-Encoding 的值。
    2. 決定要求中傳送的酬載格式。
    3. 如果 Content-Encoding 標頭的值位於 支援的編碼清單中,但要求酬載的格式與 Content-Encoding 標頭中指定的編碼不符,這就是問題的原因。

      要求範例:

      curl -v "http://HOSTALIAS/v1/testgzip" -H "Content-Encoding: gzip" -X POST -d @request_payload.zip
      

      上述範例要求會將值 gzip 傳送至 Content-Encoding 標頭,這是 Apigee Edge 支援的編碼方式。不過,要求酬載 request_payload.zip 為 ZIP 格式。因此,這項要求會失敗,並傳回 400 Bad Request 狀態碼和錯誤代碼:messaging.adaptors.http.flow.DecompressionFailureAtRequest

    訊息處理器記錄

    如要使用訊息處理器記錄進行驗證,請按照下列步驟操作:

    如果您是私有雲使用者,則可使用訊息處理器記錄檔,判斷 HTTP 400 錯誤的關鍵資訊。

    1. 如要使用 API 監控、追蹤工具或 NGINX 存取記錄判斷失敗要求的訊息 ID,請參閱「常見診斷步驟」。
    2. 在訊息處理器記錄中搜尋郵件 ID:

      /opt/apigee/var/log/edge-message-processor/logs/system.log

    3. 您會看到下列其中一項例外狀況:

      情境 1

      情境 1:API 要求含有 Content-Encoding: gzip 標頭

      2021-07-28 10:21:16,861  NIOThread@0 ERROR HTTP.SERVER -
      HTTPServer$Context.onInputException() : Message id:rt-57-1
      SSLClientChannel[Accepted: Remote:192.168.199.8:8443
      Local:192.168.80.234:44284]@28469 useCount=1 bytesRead=0
      bytesWritten=28764 age=2739893ms  lastIO=0ms
      isOpen=true.onExceptionRead exception: {}
      java.util.zip.ZipException: Not in GZIP format
      
      2021-07-28 10:21:16,862  NIOThread@0 ERROR ADAPTORS.HTTP.FLOW -
      AbstractRequestListener.onException() : Request:POST, uri:/test,
      message Id:rt-57-1, exception:java.util.zip.ZipException: Not in GZIP format,
      context:Context@71ea5ac input=ClientInputChannel(SSLClientChannel[Accepted:
      Remote:192.168.199.8:8443 Local:192.168.80.234:44284]@28469 useCount=1
      bytesRead=0 bytesWritten=28764 age=2739894ms  lastIO=0ms  isOpen=true)
      2021-07-28 10:21:16,862  NIOThread@0 INFO  HTTP.SERVICE -
      ExceptionHandler.handleException() :
      Exception java.util.zip.ZipException: Not in GZIP format occurred while writing
      to channel null
      2021-07-28 10:21:16,863  NIOThread@0 INFO  HTTP.SERVICE -
      ExceptionHandler.handleException() : Exception trace:
      java.util.zip.ZipException: Not in GZIP format
      

      上述錯誤訊息中的 java.util.zip.ZipException: Not in GZIP format 行指出,雖然 Content-Encoding 指定為 gzip,但要求酬載並未以 GZIP 格式傳送。因此,Apigee Edge 會擲回例外狀況,並將 400 狀態碼和錯誤代碼 messaging.adaptors.http.flow.DecompressionFailureAtRequest 傳回給用戶端應用程式。

      情境 #2

      情境 2:API 要求含有「Content-Encoding: deflate」標頭

      2021-07-28 15:26:31,893  NIOThread@1 ERROR HTTP.SERVER -
      HTTPServer$Context.onInputException() : Message id:rt-47875-1
      SSLClientChannel[Accepted: Remote:192.168.199.8:8443
      Local:192.168.81.72:45954]@29276 useCount=1 bytesRead=0
      bytesWritten=37230 age=3498856ms  lastIO=1ms
      isOpen=true.onExceptionRead exception: {}
      java.util.zip.ZipException: incorrect header check
                        ….
      Caused by: java.util.zip.DataFormatException: incorrect header check
             ..
      2021-07-28 15:26:31,894  NIOThread@1 ERROR ADAPTORS.HTTP.FLOW -
      AbstractRequestListener.onException() : Request:POST, uri:/test,
      message Id:rrt-47875-1, exception:java.util.zip.ZipException:
      incorrect header check, context:Context@69b3ac45
      input=ClientInputChannel(SSLClientChannel[Accepted:
      Remote:192.168.199.8:8443 Local:192.168.81.72:45954]@29276
      useCount=1 byt	esRead=0 bytesWritten=37230 age=3498856ms
      lastIO=1ms  isOpen=true)
      

      上述錯誤訊息中的 java.util.zip.ZipException: incorrect header checkCaused by: java.util.zip.DataFormatException: incorrect header check 這幾行表示要求酬載未以 deflate 格式傳送,且與 deflate 的 Content-Encoding 標頭中指定的編碼不符。因此,Apigee Edge 會擲回例外狀況,並向用戶端應用程式傳回 400 狀態碼和錯誤代碼 messaging.adaptors.http.flow.DecompressionFailureAtRequest

解析度

  1. 如果 Apigee Edge 的 API Proxy 流程和後端伺服器不需要壓縮要求酬載,請「不要」傳遞 Content-Encoding 標頭。如需壓縮要求酬載,請前往步驟 2。
  2. 請確保用戶端應用程式一律會傳送下列項目:
    • 要求中 Content-Encoding 標頭的值,可以是 支援的任何編碼
    • 傳送至 Apigee Edge 的要求酬載採用支援的格式,且符合 Content-Encoding 標頭中指定的編碼格式
  3. 在上述範例中,要求酬載為 ZIP 格式,但要求標頭指定 Content-Encoding: gzip。如要修正問題,請將要求標頭傳送為 Content-Encoding: gzip,並將要求酬載也傳送為 gzip 格式:
    curl -v "https://HOSTALIAS/v1/testgzip" -H "Content-Encoding: gzip" -X POST -d @request_payload.gz
    

規格

Apigee Edge 會根據下列 RFC 規格,傳回狀態碼 400 Bad Request 和錯誤碼 messaging.adaptors.http.flow.DecompressionFailureAtRequest

規格
RFC 7231 第 6.5.1 節
RFC 7231 的 3.1.2.2 節

如果仍需要 Apigee 支援團隊協助,請參閱「 必須收集診斷資訊」。

必須收集診斷資訊

收集下列診斷資訊,然後聯絡 Apigee Edge 支援團隊

如果您是公有雲使用者,請提供下列資訊:

  • 機構名稱
  • 環境名稱
  • API Proxy 名稱
  • 用於重現 400 錯誤的完整 curl 指令
  • API 要求的追蹤記錄檔

如果您是 Private Cloud 使用者,請提供下列資訊:

  • 失敗要求顯示的完整錯誤訊息
  • 環境名稱
  • API Proxy 套裝組合
  • API 要求的追蹤記錄檔
  • NGINX 存取記錄 /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

    說明: ORGENVPORT# 會替換為實際值。

  • 訊息處理器系統記錄 /opt/apigee/var/log/edge-message-processor/logs/system.log