502 閘道錯誤 - 重複標頭

您正在查看 Apigee Edge 說明文件。
查看 Apigee X 說明文件
資訊

問題

用戶端應用程式會取得 502 Bad Gateway 的 HTTP 狀態碼,以及錯誤代碼 protocol.http.DuplicateHeader 做為 API 呼叫的回應。

錯誤訊息

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

HTTP/1.1 502 Bad Gateway

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

{
   "fault":{
      "faultstring":"Duplicate Header \"Expires\"",
      "detail":{
         "errorcode":"protocol.http.DuplicateHeader"
      }
   }
}

可能原因

如果特定 HTTP 標頭不得在 Apigee Edge 中重複,且在後端伺服器傳送至 Apigee Edge 的 HTTP 回應中,出現多次相同或不同的值,就會發生這個錯誤。

根據 RFC 7230 的第 3.2.2 節:欄位順序寄件者「不得」在郵件中產生具有相同欄位名稱的多個標頭欄位,除非該標頭欄位的完整欄位值定義為以半形逗號分隔的清單 (即#(values)] 或標頭欄位是已知的例外狀況。如果 Apigee Edge 發現不能使用重複項目的特定標頭,且會在目標/後端伺服器傳送的「HTTP 回應」 中多次傳送,就會傳回 502 Bad Gateway 和錯誤代碼 protocol.http.DuplicateHeader

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

原因 說明 適用的疑難排解指示
回應中的標頭重複 後端伺服器的回應包含重複的標頭。 Edge Public and Private Cloud 使用者

常見診斷步驟

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

API Monitoring

如何使用 API Monitoring 診斷錯誤:

  1. 適當角色的使用者 登入 Apigee Edge UI
  2. 切換至您想要調查問題的機構。

  3. 前往「分析」>「API 監控」>「調查」頁面。
  4. 請選取您發現錯誤的特定時間範圍。
  5. 確認「Proxy」篩選器已設為「全部」
  6. 將「Fault Code」與「Time」進行比較。
  7. 選取含有錯誤代碼 protocol.http.DuplicateHeader 的儲存格,如下所示:

    (查看較大的圖片)。

  8. 錯誤代碼 protocol.http.DuplicateHeader 的資訊如下所示:

    (查看較大的圖片)。

  9. 確認「Status Code」502,如以上範例所示。
  10. 按一下「查看記錄檔」,然後展開失敗要求的資料列。
  11. 在「記錄」視窗中,留意下列詳細資料:

    • 狀態碼: 502
    • Fault 資料來源: target
    • 錯誤代碼: protocol.http.DuplicateHeader
  12. 「Fault Source」target,表示後端伺服器的回應包含重複的標頭。

追蹤工具

如何使用追蹤工具診斷錯誤:

  1. 啟用追蹤工作階段,並採取下列任一做法:
    1. 等待發生 502 Bad Gateway 錯誤,或
    2. 如果可以重現問題,請發出 API 呼叫並重現 502 Bad Gateway 錯誤
  2. 確保已啟用「Show all Flow Infos」

  3. 請選取其中一個失敗的要求,然後檢查追蹤記錄。
  4. 瀏覽追蹤記錄的不同階段,找出發生錯誤的位置。
  5. 您會在「傳送至目標伺服器的要求」階段之後的流程中找到這個錯誤,如下所示:

    (查看較大的圖片)。

  6. 記下追蹤記錄中的錯誤值。

    上述範例追蹤記錄顯示錯誤為 Duplicate Header "Expires"。由於 Apigee 會在要求傳送至後端伺服器後引發錯誤,因此這表示後端伺服器多次傳送了 Expires 標頭。

  7. 前往追蹤記錄中的「AX」(Analytics (分析) 已記錄) 階段,然後按一下該階段。
  8. 向下捲動至「階段詳細資料 - 回應標頭」區段,確定 X-Apigee-fault-codeX-Apigee-fault-source 的值,如下所示:

    (查看較大的圖片)。

  9. 您會看到 X-Apigee-fault-codeX-Apigee-fault-source 的值為 protocol.http.DuplicateHeadertarget,表示這項錯誤是因為後端伺服器為回應標頭 Expires 傳遞了重複的標頭。
    回應標頭
    X-Apigee-fault-code protocol.http.DuplicateHeader
    X-Apigee-fault-source target
  10. 檢查您是否正在使用 Proxy 鏈結,也就是目標伺服器或目標端點在 Apigee 中叫用另一個 Proxy 的情況。

    1. 如要判斷情況,請返回「Request sent to target」伺服器階段。按一下「顯示 Curl」

    2. 系統會隨即開啟「Curl for Request Sent to Target Server」視窗,您可以在其中決定目標伺服器主機別名。

    3. 如果目標伺服器主機別名指向虛擬主機別名,就表示其為 Proxy 鏈結。在這種情況下,您必須針對鏈結 Proxy 重複上述所有步驟,直到找出實際導致 502 Bad Gateway 錯誤的原因為止。
    4. 如果目標伺服器主機別名指向後端伺服器,就表示後端伺服器會在回應中將重複的標頭傳送至 Apigee。

NGINX

如何使用 NGINX 存取記錄檔診斷錯誤:

  1. 如果您是 Private Cloud 使用者,即可使用 NGINX 存取記錄檔來判斷 HTTP 502 錯誤的相關重要資訊。
  2. 查看 NGINX 存取記錄檔:

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

    其中: ORGENVPORT# 會替換為實際值。

  3. 搜尋特定時間範圍內是否有任何 502 錯誤 (如果問題過去發生),或是否有任何要求仍失敗並顯示 502
  4. 如果在 X-Apigee-fault-code X-Apigee-fault-code 的值相符的情況下發現任何 502 錯誤,請判斷 X-Apigee-fault-code 的值。

    NGINX 存取記錄中的 502 錯誤示例:

    上述 NGINX Access 記錄範例項目針對 X- Apigee-fault-codeX-Apigee-fault-source 提供下列值:

    回應標頭
    X-Apigee-fault-code protocol.http.DuplicateHeader
    X-Apigee-fault-source target

原因:回應中有重複的標頭

診斷

  1. 使用 API 監控或 NGINX 存取記錄檔,按照常見診斷步驟說明觀察到錯誤的「Fault Code」和「Fault Source」
  2. 如果「Fault Source」的值為 target,表示目標伺服器傳送的回應包含重複的標頭。
  3. 您可以透過下列任一方法,判斷哪些實際標頭在回應中會傳送一次以上:

    錯誤訊息

    使用錯誤訊息:

    1. 如果您可以存取 Apigee Edge 傳送的完整錯誤訊息,請參閱 faultstringfaultstring 包含已傳送一次的標頭名稱。

      錯誤訊息示例:

      "faultstring":"Duplicate Header \"Expires\""
      
    2. 在上述錯誤訊息中,您可以看到標頭 Expires 已多次傳送,如 faultstring 所示。

    實際要求

    使用實際要求:

    1. 如果您無法存取對目標伺服器所發出的實際要求,則請參閱「使用追蹤工具」步驟 10.a 和步驟 10.b,取得對應的 curl 指令。
    2. 如果您可以存取對目標伺服器應用程式的實際要求,請執行下列步驟:

      1. 呼叫目標伺服器。

        這個範例使用的目標伺服器要求範例:

        curl -X GET "https://BACKEND_SERVER_HOST/response-headers?Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT&Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT" -v
        
      2. 驗證回應中顯示的標頭清單。

        以下範例使用的目標伺服器的回應範例:

        * ...Trimmed...
        > GET /response-headers?Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT&Expires=Mon%2C%2021%20June%202021%2007%3A28%3A00%20GMT HTTP/2
        > Host: BACKEND_SERVER_HOST
        > User-Agent: curl/7.64.1
        > Accept: */*
        >
        * Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
        < HTTP/2 200
        < date: Fri, 02 Jul 2021 05:29:07 GMT
        < content-type: application/json
        < content-length: 166
        < server: gunicorn/19.9.0
        < Expires: Mon, 21 June 2021 07:28:00 GMT
        < Expires: Mon, 21 June 2021 07:28:00 GMT
        < access-control-allow-origin: *
        < access-control-allow-credentials: true
        <
        ----<Response BODY>------
        * Connection #0 to host httpbin.org left intact
        * Closing connection 0
        

        在上述要求範例中,系統會多次傳送 Expires 標頭。因此,這項要求會失敗,並出現 502 Bad Gateway 錯誤和錯誤代碼:protocol.http.DuplicateHeader

      3. 如果名稱出現在 faultstring 的標頭在後端伺服器的回應中多次出現,這就是導致這項錯誤的原因。在上述情況中,系統會重複傳送 Expires 標頭。

解析度

修正重複問題

選項 #1 [建議做法] 修正後端伺服器,不要納入重複的標頭

  1. 分析特定後端伺服器傳送重複標頭 Expires 的原因,並確認 API Proxy 是否能接受該標頭。在大多數情況下,根據 HTTP 規格 RFC7230 並不需要這個值。
  2. 如果不想要傳送重複的標頭,請修改目標伺服器應用程式。在上述範例中,我們發現標頭 Expires 因相同值傳送兩次,而這種情況並不理想。如要解決這個問題,請確保目標伺服器只傳遞 Expires 標頭一次。
  3. 如果可行,但您想要允許重複的標頭,請參閱「選項 #2 使用 CwC 屬性」。

CwC

選項 #2 使用 CwC 屬性

Apigee 提供 CwC 屬性 HTTPHeader.<HeaderName>,可讓用戶端應用程式和目標伺服器將重複的標頭傳送至 Apigee Edge 中的 API Proxy。

CwC 屬性
HTTPHeader.<HeaderName> allowDuplicates,multivalued

舉例來說,您可以在訊息處理器上設定下列屬性,允許重複項目及標頭 Expires 的多個值。

HTTPHeader.Expires=allowDuplicates, multiValued
  1. 如果您是私人 Cloud 使用者,可以按照 設定訊息處理器使用重複的標頭教學指南的說明,設定屬性來避免 Apigee Edge 引發 502 Bad Gateway 錯誤。
  2. 如果您是公開雲端使用者,請與 Apigee Edge 支援團隊聯絡,為貴機構設定這項屬性。

規格

Apigee 會傳回 502 Bad Gateway 錯誤回應,因為它預期的後端伺服器會按照下列 RFC 規範運作:

規格
RFC 7230 第 3.2.2 節:欄位順序
RFC 7230 第 3.2 節:標頭欄位

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

必須收集診斷資訊

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

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

  • 機構組織名稱
  • 環境名稱
  • API Proxy 名稱
  • 完成用來重現 502 錯誤的 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