設定郵件處理工具以允許重複的標頭

您正在查看 Apigee Edge 說明文件。
前往 Apigee X 說明文件
info

根據 HTTP 規格 RFC 7230,第 3.2.2 節:欄位順序,Apigee Edge 預期來自用戶端的 HTTP 要求或來自後端伺服器的 HTTP 回應,不會包含相同或不同值的相同標頭,除非特定標頭有例外狀況且允許重複。

根據預設,Apigee Edge 允許重複值和多個值傳遞至大多數的 HTTP 標頭。但不允許標頭不允許重複和多個值中列出的特定標頭。 因此:

  • 如果用戶端多次傳送含有特定標頭的 HTTP 要求,或是針對 HTTP 標頭傳送多個值,而這些要求在 Apigee Edge 中不能有重複/多個值,您會收到 400 Bad Request 錯誤代碼 protocol.http.DuplicateHeader
  • 同樣地,如果後端伺服器多次傳送含有特定標頭的 HTTP 回應,或是針對 HTTP 標頭傳送多個值,但 Apigee Edge 中不允許出現重複或多個值,您就會收到 502 Bad Gateway 錯誤代碼 protocol.http.DuplicateHeader 的訊息。

如要解決這些錯誤,建議的解決方案是修正用戶端應用程式和後端伺服器,以免傳送重複的標頭,並遵循 RFC 7230,第 3.2.2 節:欄位順序的規格,如以下疑難排解操作手冊所述:

不過,在某些情況下,您可能需要新增例外狀況,以便為部分 HTTP 標頭納入重複值和多個值。在這種情況下,您可以在訊息處理器層級設定屬性 HTTPHeader.HEADER_NAME,允許特定 HTTP 標頭重複使用標頭和多個值。

本文將提供這項屬性的相關資訊,說明如何啟用這項屬性以避免上述錯誤,並分享相關最佳做法。

允許重複和多個值的 HTTP 標頭屬性

Apigee Edge 提供下列兩個屬性,用於控制允許重複和多個 HTTP 標頭值的行為。請注意,這些設定只能在使用 如何設定 Edge 一文中說明的符記語法下,在訊息處理器上進行。

屬性名稱 說明 允許的值
HTTPHeader.ANY

這個屬性可指出是否允許所有 HTTP 標頭 (包括用戶端發出的 HTTP 要求或後端伺服器傳送至 Apigee Edge 的 HTTP 回應所傳送的自訂標頭) 重複或多重值。

預設值:

multiValued, allowDuplicates,

  1. blank:不允許重複的 HTTP 標頭和多個值。
  2. multiValued:將多值標頭分割為多個標頭。HTTP 標頭可以有多個值,但不允許重複。已啟用 multiValued 值,這表示 test-header=a,b 會轉換為 test-header=atest-header=b.
  3. allowDuplicates:允許多個名稱相同的 HTTP 標頭 (重複)。
  4. multiValued, allowDuplicates:HTTP 標頭允許多個值和重複值。

HTTPHeader.HEADER_NAME

這個屬性可用來覆寫特定標頭的行為 (從 HTTPHeader.ANY 的指定值)

同上。

標頭不得使用重複和多個值

如先前所述,Apigee Edge 預設允許大多數 HTTP 標頭重複及多個值。這是因為屬性 HTTPHeader.ANY 已設為 multiValued, allowDuplicates. 值。

設定已覆寫

針對某些特定標頭,系統會使用下列任一方法覆寫預設設定:

  • HTTPHeader.HEADER_NAME=multiValued, allowDuplicates

    這項設定不會變更預設行為。 也就是說,這個特定標題可以重複和多個值

  • HTTPHeader.HEADER_NAME=

    這項設定會變更預設行為。也就是說,特定標頭不得有重複和多個值

判斷不得使用重複和多個值的標頭

本節說明如何辨識下列項目:

  • 在 Apigee Edge 私有雲設定中,不得使用重複和多個值 的特定標頭;以及
  • 含有預先存在設定的特定標頭
  1. 在訊息處理器機器上,搜尋 /opt/apigee/edge-message-processor/conf 目錄中的屬性 HTTPHeader.,如以下所示:

    grep -ri "HTTPHeader." /opt/apigee/edge-message-processor/conf
    

    輸出內容範例:

    # grep -ri "HTTPHeader" /opt/apigee/edge-message-processor/conf
    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.ANY=allowDuplicates, multiValued
    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Connection=allowDuplicates, multiValued
    … <snipped>
    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Host=
    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Expires=
    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Date=allowDuplicates
    …
    <snipped>
  2. 如「設定覆寫」一節所述,請注意上述範例輸出內容中的下列資訊:
    1. HTTP 標頭 Connection 已遭到覆寫,但允許含有重複項目和多個值
    2. HTTP 標頭 HostExpires 會遭到覆寫,且不允許有重複和多個值
    3. HTTP 標頭 Date 會被覆寫,且允許重複,但不允許有多個值
    4. 此處顯示的所有標頭 (上例中的 ConnectionHostExpiresDate) 都稱為本文件中具有既有設定的標頭。

Apigee Edge 的行為

下表說明當標頭以重複的形式傳送,且具有多個值時,Apigee Edge 的行為,具體取決於 HTTPHeader 屬性在訊息處理器上如何設定,並附上 test-headerHTTPHeader 範例。

要求 傳出標題 (以 conf/http.properties+HTTPHeader.test-header= 的值為準)
<空白> allowDuplicates multiValued allowDuplicates, multiValued (預設)
test‑header=a,b test‑header=a,b test‑header=a,b

protocol.http.
DuplicateHeader

我們會在內部將 test-header=a,b 分成以下兩個部分:

  • test-header=a
  • test-header=b

然後,系統會擲回 DuplicateHeader 錯誤。

test‑header=a,b

我們內部會將 test-header=a,b 分為:

  • test-header=a
  • test-header=b

但原始表單會傳送至目標。

test‑header=a
test‑header=b
protocol.http.
DuplicateHeader
test‑header=a
test‑header=b
protocol.http.
DuplicateHeader
test‑header=a
test‑header=b

事前準備

在使用本文件中的步驟前,請先瞭解如何設定私有雲端的 Edge 屬性,詳情請參閱「 如何設定 Edge」。

設定標頭的 allowDuplicates 和多個值

允許重複和多個值的 HTTP 標頭屬性所述,屬性 HTTPHeader.ANY = allowDuplicates, multiValued 的值表示在 Apigee Edge 中,所有標頭都允許重複和多個值。不過,某些標頭的值會明確覆寫,以免使用 HTTPHeader.HEADER_NAME 屬性時出現重複標頭或多個值。

本節說明如何設定屬性 HTTPHeader.HEADER_NAME,以允許訊息處理器上任何這類 HTTP 標頭重複和多個值,並按照如何設定 Edge 中的語法使用對應的符記。

在本節中,我們將使用 Expires (和 myheader) 做為標頭範例,以便允許重複和多個值,相關說明如下:

  1. Determine the current value of the property HTTPHeaderHEADER_NAME 使用下列指令,確認系統未啟用允許重複和多個值的功能:
    grep -ri "HTTPHeader.HEADER_NAME" /opt/apigee/edge-message-processor/conf
    

    舉例來說,如要設定 Expires 標頭的屬性,請在「訊息處理器」上檢查屬性 HTTPHeader.Expires 權杖目前的值:

    grep -ri "HTTPHeader.Expires" /opt/apigee/edge-message-processor/conf
    

    上述指令的輸出結果會產生下列其中一種結果:

    1. 屬性設為空白,則表示值已覆寫 (這是具有預先存在設定的標頭),因此不允許重複標頭和多個值。也就是說,您無法在 HTTP 要求或 HTTP 回應中傳送 Expires 標頭,且傳送次數不得超過一次。
    2. 如果特定屬性沒有任何命中,表示該值未遭覆寫 (且這不是含有預先存在設定的標頭)。也就是說,在 HTTP 要求或 HTTP 回應傳送至 Apigee Edge 時,可將特定標頭傳送多次 (允許重複)。
    3. 屬性會設定為 allowDuplicates, multiValued 值,這表示該值已明確覆寫 (這是具有預先存在設定的標頭)。也就是說,在 HTTP 要求或 HTTP 回應傳送至 Apigee 時,可傳送多個特定標頭 (允許重複)。

    搜尋指令的輸出內容範例:

    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Expires=

    上述的輸出內容範例顯示屬性 HTTPHeader.Expires 已設定為空白。這表示屬性已覆寫不允許標頭 Expires 有重複或多個值

  2. 如果您發現對應特定標頭的屬性已明確覆寫,以不允許重複或多個值為準,如上述範例輸出內容所示,只有在這種情況下,才執行下列步驟。如果未明確覆寫,則請略過本節的其餘步驟。
  3. 編輯。如果不存在,您可以建立它:
    /opt/apigee/customer/application/message-processor.properties

    舉例來說,如要使用 vi 開啟檔案,請輸入以下內容:

    vi /opt/apigee/customer/application/message-processor.properties
    
  4. 按照以下格式新增一行:
    conf_http_HTTPHeader.Expires=allowDuplicates, multiValued
  5. 儲存變更。
  6. 請確認屬性檔案的擁有者是 apigee 使用者。如果不是,請執行下列指令:

    chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
    
  7. 重新啟動訊息處理工具:

    /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
    

    如要在不影響流量的情況下重新啟動,請參閱「 滾動式重新啟動且不影響流量的訊息處理器」一文。

  8. 如果您有多個訊息處理器,請對所有訊息處理器重複上述步驟。

確認標頭已設為含有重複和多個值

本節說明如何驗證特定標頭的屬性 HTTPHeader.HEADER_NAME 已成功更新,以便允許訊息處理器中的重複項目。

我們會使用 Expires 做為範例標頭,並檢查對應的屬性 HTTPHeader.Expires 是否已更新。

即使您使用權杖 conf_http_HTTPHeader.Expires 更新訊息處理器的值,仍須確認已使用新值設定實際的 HTTPHeader.Expires 屬性。

  1. 在訊息處理器機器上,搜尋 /opt/apigee/edge-message-processor/conf 目錄中的屬性 HTTPHeader.HEADER_NAME,並檢查是否已設定新值,如下所示:
    grep -ri "HTTPHeader.HEADER_NAME" /opt/apigee/edge-message-processor/conf
    

    舉例來說,如果您想確認屬性 HTTPHeader.Expires 是否已設為新值,請執行下列指令:

    grep -ri "HTTPHeader.Expires" /opt/apigee/edge-message-processor/conf
    
  2. 如果成功在訊息處理器上為 HTTPHeader.HEADER_NAME 設定新的值,上述指令就會在 http.properties 檔案中顯示新的值。
  3. 設定 allowDuplicatesmultiValued 後,上述指令的結果範例如下:

    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Expires=allowDuplicates, multiValued
  4. 請注意,在上述範例輸出內容中,屬性 HTTPHeader.Expires 已在 http.properties 中設為新值 allowDuplicates, multiValued。這表示在訊息處理器上已成功設定允許 HTTPHeader 中重複和多個值的行為。
  5. 如果仍看到 HTTPHeader.HEADER_NAME 屬性的舊值,請確認您已正確遵循「設定 allowDuplicates 和多個標頭值」一文所述的所有步驟。如果您遺漏了任何步驟,請再次正確重複執行所有步驟。

    請確認您的 Proxy 能正常運作,尤其是在 Proxy 中取得及設定標頭時,有功能邏輯的情況。

  6. 如果您仍無法修改屬性,請與 Apigee Edge 支援團隊聯絡

停用標頭的 allowDuplicates

本節說明如何根據如何設定 Edge 一文中的語法,使用對應的符記,將訊息處理器上的特定 HTTP 標頭設為「禁止重複和多個值」。HTTPHeader.{Headername}

在本節中,我們將使用 Expires (和 myheader) 做為標頭範例,這種標頭不允許重複,如下所述:

  1. Determine the current value of the property HTTPHeaderHEADER_NAME 以確保未停用,以便使用下列指令允許重複和多個值:
    grep -ri "HTTPHeader.HEADER_NAME" /opt/apigee/edge-message-processor/conf
    

    舉例來說,如果您嘗試設定 Expires 標頭的屬性,請在訊息處理器上檢查屬性 HTTPHeader.Expires 符記的目前值:

    grep -ri "HTTPHeader.Expires" /opt/apigee/edge-message-processor/conf
    

    上述指令的輸出結果會產生下列其中一種情況:

    1. 如果屬性設為空白,則表示值 i已覆寫為「不允許重複標頭和多個值」。也就是說,您無法在 HTTP 要求或 HTTP 回應中,將 Expires 標頭傳送超過一次。
    2. 特定資源沒有命中,這代表該值不會覆寫,且這是否為現有設定的 NOT 標頭。這表示,該特定標頭可以在 HTTP 要求或 HTTP 回應至 Apigee Edge 中重複傳送 (允許重複)。
    3. 屬性會設為 allowDuplicates, multiValued 值,這表示值已明確覆寫,且這是現有的設定。不過,這表示特定標頭可在 HTTP 要求或 HTTP 回應中傳送不只一次 (允許重複)。

    輸出內容範例 #1

    搜尋指令的輸出內容範例 #1:

    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Expires=allowDuplicates, multiValued

    範例輸出結果顯示屬性 HTTPHeader.Expires 已設為 allowDuplicates, multiValued。這表示屬性 會遭到覆寫,以便允許標頭 Expires 重複或多個值

    輸出內容範例 #2

    搜尋指令的範例指令和輸出內容 #2

    grep -ri "HTTPHeader.myheader" /opt/apigee/edge-message-processor/conf
    

    範例輸出內容沒有任何輸出內容,這表示屬性 HTTPHeader.myheader 預設為 allowDuplicates, multiValued。這也表示,對於 myheader 標頭,屬性不會遭到覆寫

  2. 如果你注意到以下任一種情況,請執行本節的其餘步驟:
    1. 對應於特定標頭的屬性 會遭到覆寫,以便允許重複和多個值,如上方的輸出結果範例 #1 所示 (標頭含有預先存在的設定)
    2. 資源與特定標頭相對應,但沒有任何命中,如上方的範例輸出 #2所示 (不是具有預先存在設定的標頭)

    否則請略過本節的其餘步驟。

  3. 編輯下列檔案。如果不存在,您可以建立它。
    /opt/apigee/customer/application/message-processor.properties

    舉例來說,如要使用 vi 開啟檔案,請輸入以下內容:

    vi /opt/apigee/customer/application/message-processor.properties
    
  4. 在屬性檔案中加入以下格式的一行:

    現有設定

    情境 #1:包含現有設定的標頭:

    conf_http_HTTPHeader.Expires=

    沒有先前設定

    情境 #2:不是具有先前設定的標頭:

    conf/http.properties+HTTPHeader.myheader=
  5. 儲存變更。
  6. 確認屬性檔案是由 apigee 使用者所擁有。如果沒有,請執行下列指令:
    chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
    
  7. 重新啟動訊息處理器:
    /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
    

    如要在不影響流量情況下重新啟動,請參閱 在不影響流量情況下,分批重新啟動訊息處理器

  8. 如果您有多個訊息處理器,請對所有訊息處理器重複上述步驟。

確認標頭已設定為不允許重複和多個值

本節說明如何驗證特定標頭的 HTTPHeader.HEADER_NAME 屬性是否已成功更新,以免在訊息處理器上出現重複項目。

我們會使用 Expires (和 myheader) 做為範例標頭,並檢查是否已更新對應的屬性 HTTPHeader.Expires (和 HTTPHeader.myheader)。

  1. 在訊息處理器機器上,搜尋 /opt/apigee/edge-message- processor/conf 目錄中的屬性 HTTPHeader.HEADER_NAME,並檢查是否已設定新值,如下所示:

    grep -ri "HTTPHeader.HEADER_NAME" /opt/apigee/edge-message-processor/conf
    

    舉例來說,如果您想檢查屬性 HTTPHeader.Expires 是否已設為新值,可以執行下列指令:

    現有設定

    grep -ri "HTTPHeader.Expires" /opt/apigee/edge-message-processor/conf
    

    沒有任何現有設定

    grep -ri "HTTPHeader.myheader" /opt/apigee/edge-message-processor/conf
    
  2. 如果已成功為 Message Processor 的 HTTPHeader.HEADER_NAME I 設定新的 HTTP 標頭值,則上述指令會在 http.properties 檔案中顯示新值。
  3. 停用 allowDuplicates 後,上述指令的結果範例如下:

    現有設定

    情境 #1Expires Header (含有預先設定的標頭)

    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.Expires=

    沒有先前設定

    情境 2:myheader 標頭 (非現有設定的標頭)

    /opt/apigee/edge-message-processor/conf/http.properties:HTTPHeader.myheader=
  4. 請注意,在上述範例輸出內容中,屬性 HTTPHeader.Expires ( 和 HTTPHeader.myheader) 已設為新的值 {blank} in http.properties。這表示訊息處理器已成功停用允許重複和特定 HTTP 標頭 Expires (和 myheader) 的多個值的行為。
  5. 如果仍看到 HTTPHeader.Expires (or HTTPHeader.myheader) 屬性的舊值,請確認您已正確遵循「設定 allowDuplicates 和多個標頭值」一文所述的所有步驟。如果遺漏任何步驟,請再次正確重複執行所有步驟。

    請確認 Proxy 能正常運作,尤其是在 Proxy 中取得及設定標頭時,有功能邏輯的情況。

  6. 如果您仍無法修改屬性,請與 Apigee Edge 支援團隊聯絡。