您正在查看 Apigee Edge 說明文件。
查看 Apigee X 說明文件。 資訊
問題
用戶端應用程式會取得 500 Internal Server Error
的 HTTP 狀態碼,以及錯誤代碼 protocol.http.BadFormData
做為 API 呼叫的回應。
錯誤訊息
用戶端應用程式會取得以下回應代碼:
HTTP/1.1 500 Internal Server Error
此外,您可能會遇到以下錯誤訊息:
{ "fault":{ "faultstring":"Bad Form Data", "detail":{ "errorcode":"protocol.http.BadFormData" } } }
表單資料
在深入說明如何解決這個問題前,請先瞭解什麼是表單資料。
表單資料是使用者通常透過 HTML 表單提供的資訊,其中包含文字輸入方塊、按鈕或核取方塊等元素。表單資料通常會以一系列鍵/值組合的形式傳送,做為 HTTP 要求或回應的一部分。
表單資料傳輸
- Content-Type: application/x-www-form-urlEncoding
- 如果表單資料的大小很小,資料會以鍵/值組合的形式傳送,其中包含:
- 兩個索引鍵中編碼的字元,如 表單 - 第 17.13.4.1 節所述規則
- 標題
Content-Type: application/x-www-form-urlencoded
包含表單資料的要求示例:
curl https://HOSTALIAS/somepath -H "Content-Type: application/x-www-form-urlencoded" -d "username=abc@google.com&pasword=secret123"
- 鍵和值中的任何非英數字元都會
編碼百分比,也就是以字元三元組
%HH
表示,包含百分比符號後接兩個十六進位數字,代表特定字元的 ASCII 代碼。 - 因此,即使表單資料可以使用百分比符號 (
%
),仍會被解讀為特殊逸出序列的起始。因此,如果表單資料需要在鍵或值中包含百分比符號 (%
),則應以%25,
代表百分比符號 (%
) 字元的 ASCII 編碼。
- 如果表單資料的大小很小,資料會以鍵/值組合的形式傳送,其中包含:
- Content-Type:Multipart/form-data
如要傳輸大量的二進位資料或包含非 ASCII 字元的文字,您可以按照 表單 - 第 17.13.4.2 節的說明,透過
Content-Type:
multipart/form-data 傳送資料。
可能原因
只有在符合下列所有條件時,才會發生這個錯誤:
- 用戶端傳送至 Apigee Edge 的 HTTP 要求包含下列內容:
Content-Type: application/x-www-form-urlencoded
和- 含有百分比符號 (
%
) 或百分比符號 (%
) 的表單資料,後面接著禁止使用的十六進位字元,如 表單 - 第 17.13.4.1 節所述。
Apigee Edge 中的 API Proxy 會透過「ExtractVariables」或 AssignMessage 政策,讀取特定表單參數,其中包含不允許在要求流程中使用的字元。
舉例來說,如果表單資料包含原狀 (
%
) 原樣 (不含編碼) 或百分比符號 (%
),後接鍵和/或值中的任何無效的十六進位字元,就會發生這個錯誤。這項錯誤的可能原因如下:
原因 說明 適用的疑難排解指示 要求中的表單參數含有不允許的字元 用戶端在 HTTP 要求中傳遞的表單參數包含任何不允許使用的字元。 Edge Public and Private Cloud 使用者
常見診斷步驟
請使用下列其中一種工具/技巧診斷這項錯誤:
API Monitoring
如何使用 API Monitoring 診斷錯誤:
- 以適當角色的身分 登入 Apigee Edge UI。
切換至您想要調查問題的機構。
- 前往「分析」>「API 監控」>「調查」頁面。
- 請選取你發現錯誤的特定時間範圍。
將「Fault Code」與「Time」進行比較。
選取含有錯誤代碼
protocol.http.BadFormData
的儲存格,如下所示:(查看較大的圖片)。
錯誤代碼
protocol.http.BadFormData
的相關資訊如下所示:(查看較大的圖片)。
按一下「查看記錄」,然後展開失敗要求的資料列。
- 在「記錄檔」視窗中記下下列詳細資料:
- 狀態碼:
500
- Fault 資料來源:
proxy
- 錯誤代碼:
protocol.http.BadFormData
- 違規政策:
extractvariables/EV-ExtractFormParams
- 狀態碼:
- 如果「Fault Source」為
proxy
、「Fault Code」為protocol.http.BadFormData
且「Fault Policy」 非空白,表示發生錯誤時,「Fault Policy」中指定政策讀取或擷取的表單資料 (表單參數) 含有任何不允許使用的字元。 - 在這個範例中,X-Apigee-fault-policy 為
extractvariables/EV- ExtractFormParams,
,這表示讀取或擷取表單參數時,名為 EV-ExtractFormParams 的 ExtractVariables 政策失敗。
追蹤工具
如何使用追蹤工具診斷錯誤:
- 啟用追蹤工作階段,然後採取下列其中一種做法:
- 等待發生
500 Internal Server Error
錯誤,或 - 如果可以重現問題,請透過 API 呼叫來重現問題
500 Internal Server Error
- 等待發生
確保已啟用「Show all FlowInfos」:
- 請選取其中一個失敗的要求,然後檢查追蹤記錄。
- 瀏覽追蹤記錄的不同階段,找出發生錯誤的位置。
一般來說,您會在其中一項政策中找到該錯誤,如下所示:
請注意,在上述範例追蹤記錄中,名為
EV-ExtractFormParams
的「ExtractVariables」政策中發生錯誤。在特定政策失敗後,前往名為 Error 的流程:
- 記下追蹤記錄中的下列值:
錯誤:
Bad Form Data
州:
PROXY_REQ_FLOW
error.class:
com.apigee.rest.framework.BadRequestException
- 錯誤
Bad Form Data
值表示表單參數中含有「不允許」使用的字元。 - 狀態
PROXY_REQ_FLOW,
表示 API Proxy 要求流程中發生錯誤。
- 錯誤
- 前往追蹤記錄中的「AX」(Analytics (分析) 已記錄) 階段,然後按一下該階段。
向下捲動至「階段詳細資料」-「錯誤標頭」區段,確定 X-Apigee-fault-code、X-Apigee-fault-source 與 X-Apigee-fault-policy 的值,如下所示:
請注意,X-Apigee-fault-code 和 X-Apigee-fault-source 的值分別為
protocol.http.BadFormData
和policy
,且 X-Apigee-fault-policy 非空白。這表示在 X-Apigee-fault-policy 中指出的特定政策是讀取或擷取表單資料 (表單參數),其中包含任何不允許使用的字元。回應標頭 值 X-Apigee-fault-code protocol.http.BadFormData
X-Apigee-fault-source policy
X-Apigee-fault-policy extractvariables/EV-ExtractFormParams
- 在這個示例中,X-Apigee-fault-policy 為
extractvariables/EV- ExtractFormParams,
,代表在讀取或擷取表單參數時,名為EV-ExtractFormParams
的 ExtractVariables 政策失敗。
NGINX
如何使用 NGINX 存取記錄檔診斷錯誤:
- 如果您是 Private Cloud 使用者,即可使用 NGINX 存取記錄檔來判斷 HTTP
500 Internal Server Error
的重要資訊。 查看 NGINX 存取記錄檔:
/opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
- 搜尋特定期間內 (問題過去是否發生),或是否有任何要求仍為
500
失敗,且錯誤代碼為protocol.http.BadFormData
。500
如果發現 X-Apigee-fault-code 與
protocol.http.BadFormData
值相符的任何500
錯誤,請判斷 X-Apigee-fault-source 和 X-Apigee-fault-policy 的值。NGINX 存取記錄中的 500 錯誤範例:
以上 NGINX 存取記錄中的範例項目,有下列「X-Apigee-fault-code」X-Apigee-fault-code和「X-Apigee-fault-source」X-Apigee-fault-code的值:
標頭 值 X-Apigee-fault-code protocol.http.BadFormData
X-Apigee-fault-source policy
X-Apigee-fault-policy extractvariables/EV-ExtractFormParams
- 請注意,X-Apigee-fault-code、X-Apigee-fault-source 的值為
protocol.http.BadFormData
,policy
各自為protocol.http.BadFormData
,X-Apigee-fault-policy 非空白。這表示在 X-Apigee-fault-policy, 中指出的特定政策期間,當錯誤發生時,會讀取或擷取表單資料 (表單參數),其中包含任何X-Apigee-fault-policy,使用的字元。 - 在這個示例中,X-Apigee-fault-policy 為
extractvariables/EV- ExtractFormParams,
,代表在讀取表單參數時,名為EV-ExtractFormParams
的 ExtractVariables 政策失敗。
原因:要求中的表單參數含有不允許使用的字元
診斷
- 使用 API 監控、追蹤工具或 NGINX 存取記錄檔,按照常見診斷步驟的說明,判斷
500 Internal Server Error
的不良程式碼、錯誤來源和不良政策。 - 如果「Fault Code」為
protocol.http.BadFormData
,「Fault Source」的值為proxy
或policy
,而「Fault Policy」不為空白,則表示在讀取或擷取表單資料 (表單參數) 時,Fault Policy 中指定的政策失敗。 - 請詳閱「Fault 政策」中列出的政策,並判斷下列資訊:
- 來源:判斷政策是否正在讀取或擷取要求或回應中的資料。
- 表單參數:判斷在政策中讀取的特定表單參數。
範例 #1
範例 #1:擷取變數政策擷取表單參數:
<ExtractVariables name="EV-ExtractFormParms"> <DisplayName>EV-ExtractFormParams</DisplayName> <Source>request</Source> <FormParam name="username"> <Pattern ignoreCase="false">{username}</Pattern> </FormParam> <FormParam name="password"> <Pattern ignoreCase="false">{password}</Pattern> </FormParam> <VariablePrefix>forminfo</VariablePrefix> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> </ExtractVariables>
在上述「ExtractVariables」政策中:
資料來源:
request
如
<Source>
元素所示表單參數:
username
和password
如
<FormParam>
元素中的<Pattern>
元素,就表示
這表示用戶端向 Apigee Edge 在 HTTP 要求中傳遞的表單參數
username
和/或password
包含不允許使用的字元。範例 #2
範例 #2:AssignMessage 政策複製表單參數:
<AssignMessage continueOnError="false" enabled="true" name="AM-CopyFormParams"> <Copy source="request"> <FormParams> <FormParam name="username"/> <FormParam name="password"/> </FormParams> </Copy> <AssignTo createNew="true" transport="http" type="request"/> </AssignMessage>
在上述「ExtractVariables」政策中:
來源:
request
如
<Copy>
元素中的source
屬性來表示表單參數:
username
和password
如
<FormParam>
元素中的name
屬性來表示
這表示
username
或password
表單參數username
或password
格式在用戶端向 Apigee Edge 的 HTTP 要求中傳遞,包含任何「不允許」使用的字元。
透過下列其中一種方法,查看步驟 3 中是否有任何字元「不允許」使用字元:
追蹤工具
如何使用追蹤工具進行驗證:
實際要求
如何使用實際要求進行驗證:
- 如果您無法存取對目標伺服器實際發出的要求,請前往「Resolution」。
- 如果您可以存取對 Apigee Edge 傳送的實際要求,請執行下列步驟:
- 檢查表單資料內容,看看其中是否含有任何不允許使用的字元,例如百分比符號 (
%
) 或百分比符號 (%
) 後面接著無效的十六進位字元。範例 #1
要求範例 #1:要求中的表單資料
curl -X GET "https://HOSTALIAS/myproxy -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=123456abc123&client_secret=c23578%ZY"
在此範例中,請注意,元素
client_secret
包含百分比符號 (%
),後面接著無效的十六進位字元ZY
。範例 #2
要求範例 #2:透過檔案傳送的表單資料:
curl -X GET "https://HOSTALIAS/myproxy -H "Content-Type: application/x-www-form-urlencoded" -d @form_data.xml
form_data.xml 的內容:
xml=<user><username>abc1234@google.com</username><password>qwerty12345!@#$%</password></user>
在此範例中,請注意,元素
password
包含百分比符號 (%
),不應在表單資料中原封不動地傳遞。
- 檢查表單資料內容,看看其中是否含有任何不允許使用的字元,例如百分比符號 (
- 在上述兩個範例中,做為 Apigee Edge 以 HTTP 要求形式傳送的表單資料,含有不允許使用的字元。
- 因此,Apigee Edge 會以
500 Internal Server Error
傳回錯誤代碼protocol.http.BadFormData
。
解析度
- 確保在用戶端透過 HTTP 要求傳送的表單資料或參數值中,兩者的特殊字元,一律會採用 表單資料 - application/x-www-form-urlcoded 所述編碼。
- 針對上述的例子,您可以修正下列問題:
範例 #1
範例 1:在要求中傳送的表單資料:
請使用符合 ASCII 代碼的特定字元 十六進位字元。舉例來說,如要傳送錢幣符號 (
$
),請使用%24
,如下所示:curl -X GET "https://HOSTALIAS/myproxy -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=123456abc123&client_secret=c23578%24"
範例 #2
要求範例 #2:透過檔案傳送的表單資料:
curl -X GET "https://HOSTALIAS/myproxy -H "Content-Type: application/x-www-form-urlencoded" -d @form_data.xml
form_data.xml 的內容:
請使用百分比 (
%
) 符號的 百分比編碼來修改檔案,使其包含%25
,如下所示:xml=<user><username>abc1234@google.com</username><password>qwerty12345!!@#$%25</password></user>
規格
Apigee Edge 預期會以下列規格傳送表單資料:
規格 |
---|
表單資料 - application/x-www-form-urlcoded |
如果您仍需取得 Apigee 支援團隊的協助,請參閱「必須收集診斷資訊」一文。
必須收集診斷資訊
如果按照上述指示操作後仍無法解決問題,請收集下列診斷資訊,然後與 Apigee Edge 支援團隊聯絡:
如果您是公開雲端使用者,請提供下列資訊:
- 機構組織名稱
- 環境名稱
- API Proxy 名稱
- 完成
curl
指令,用來重現500 Internal Server Error
錯誤代碼protocol.http.BadFormData
- API 要求的追蹤檔
如果您是 Private Cloud 使用者,請提供下列資訊:
- 觀察失敗要求的完整錯誤訊息
- 環境名稱
- API Proxy 套裝組合
- API 要求的追蹤檔
NGINX 存取記錄檔
/opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
其中:將 ORG、ENV 和 PORT# 替換為實際值。
訊息處理器系統記錄
/opt/apigee/var/log/edge-message-processor/logs/system.log