您目前查看的是 Apigee Edge 說明文件。
前往 Apigee X 說明文件。 info
問題
用戶端應用程式會收到 HTTP 狀態碼 500 Internal Server Error,以及錯誤碼 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-urlencoded
- 如果表單資料量不大,系統會以鍵/值組合的形式傳送資料,並使用:
- 兩個金鑰中的字元都必須按照 表單 - 第 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 公有和私有雲使用者
常見的診斷步驟
請使用下列其中一種工具/技術診斷這項錯誤:
API Monitoring
如要使用 API 監控功能診斷錯誤,請按照下列步驟操作:
- 以具備 適當角色的使用者身分登入 Apigee Edge UI。
切換至要調查問題的機構。
- 依序前往「Analyze」>「API Monitoring」>「Investigate」頁面。
- 選取您觀察到錯誤的特定時間範圍。
繪製「錯誤代碼」與「時間」的關係圖。
選取含有故障代碼
protocol.http.BadFormData的儲存格,如下所示:(查看較大圖片)
故障代碼
protocol.http.BadFormData的相關資訊會顯示如下:(查看較大圖片)
按一下「查看記錄」,然後展開失敗要求所在的資料列。
- 在「記錄」視窗中,記下下列詳細資料:
- 狀態碼:
500 - 錯誤來源:
proxy - 故障代碼:
protocol.http.BadFormData - 故障政策:
extractvariables/EV-ExtractFormParams
- 狀態碼:
- 如果「錯誤來源」為
proxy、「錯誤代碼」為protocol.http.BadFormData,且「錯誤政策」不為空白,則表示「錯誤政策」中指定的政策在讀取或擷取表單資料 (表單參數) 時發生錯誤,因為表單資料含有不允許使用的字元。 - 在本例中,X-Apigee-fault-policy 為
extractvariables/EV- ExtractFormParams,,表示名為 EV-ExtractFormParams 的 ExtractVariables 政策在讀取或擷取表單參數時失敗。
追蹤工具
如要使用「追蹤」工具診斷錯誤,請按照下列步驟操作:
- 啟用追蹤工作階段
和下列任一項目:
- 等待發生
500 Internal Server Error錯誤,或 - 如果可以重現問題,請發出 API 呼叫來重現問題
500 Internal Server Error
- 等待發生
確認已啟用「顯示所有流程資訊」:
- 選取其中一個失敗的要求,然後檢查追蹤記錄。
- 瀏覽追蹤記錄的不同階段,找出發生失敗的位置。
您通常會在其中一項政策中發現錯誤,如下所示:
在上述範例追蹤記錄中,請注意名為
EV-ExtractFormParams的 ExtractVariables 政策發生失敗。前往特定政策失敗後的「Error」流程:
- 請注意追蹤記錄中的下列值:
錯誤:
Bad Form Datastate:
PROXY_REQ_FLOWerror.class:
com.apigee.rest.framework.BadRequestException- 錯誤
Bad Form Data的值表示表單參數含有不允許使用的字元。 - 狀態
PROXY_REQ_FLOW,的值表示 API Proxy 的要求流程發生錯誤。
- 錯誤
- 在追蹤記錄中前往「AX」(記錄的 Analytics 資料)AX 階段,然後按一下該階段。
向下捲動至「Phase Details - Error Headers」部分,並判斷 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.BadFormDataX-Apigee-fault-source policyX-Apigee-fault-policy extractvariables/EV-ExtractFormParams- 在本例中,X-Apigee-fault-policy 為
extractvariables/EV- ExtractFormParams,,表示名為「ExtractVariables」的政策在讀取或擷取表單參數時失敗。EV-ExtractFormParams
NGINX
如要使用 NGINX 存取記錄診斷錯誤,請按照下列步驟操作:
- 如果您是私有雲使用者,可以透過 NGINX 存取記錄判斷 HTTP
500 Internal Server Error的金鑰資訊。 檢查 NGINX 存取記錄:
/opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log- 搜尋特定時間內是否有任何錯誤代碼為
500protocol.http.BadFormData的錯誤 (如果問題發生在過去),或是否有任何要求仍失敗並顯示500。 如果發現任何
500錯誤,且 X-Apigee-fault-code 與protocol.http.BadFormData的值相符,請判斷 X-Apigee-fault-source 和 X-Apigee-fault-policy 的值。NGINX 存取記錄檔中的 500 錯誤範例:
上述 NGINX 存取記錄檔的範例項目具有下列 X-Apigee-fault-code 和 X-Apigee-fault-source 值:
標頭 值 X-Apigee-fault-code protocol.http.BadFormDataX-Apigee-fault-source policyX-Apigee-fault-policy extractvariables/EV-ExtractFormParams- 請注意,X-Apigee-fault-code 和 X-Apigee-fault-source 的值分別為
protocol.http.BadFormData和policy,且 X-Apigee-fault-policy 不為空白。這表示 X-Apigee-fault-policy 中指定的特定政策在讀取或擷取表單資料 (表單參數) 時發生錯誤,因為表單資料含有不允許使用的字元。 - 在本例中,X-Apigee-fault-policy 為
extractvariables/EV- ExtractFormParams,,表示名為EV-ExtractFormParams的 ExtractVariables 政策在讀取表單參數時失敗。
原因:要求中的表單參數含有不允許的字元
診斷
- 如常見診斷步驟所述,使用 API Monitoring、Trace 工具或 NGINX 存取記錄,判斷
500 Internal Server Error的錯誤代碼、錯誤來源和錯誤政策。 - 如果「錯誤代碼」為
protocol.http.BadFormData,「錯誤來源」的值為proxy或policy,且「錯誤政策」不為空白,則表示系統在讀取或擷取表單資料 (表單參數) 時,「錯誤政策」中指定的政策失敗。 - 檢查「Fault Policy」(錯誤政策) 中指出的政策,並判斷下列資訊:
- 來源:判斷政策是從要求或回應讀取或擷取資料。
- 表單參數:判斷政策中讀取的特定表單參數。
範例 #1
範例 1:ExtractVariables 政策擷取表單參數:
<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>元素會指出這點
這表示用戶端透過 HTTP 要求傳送至 Apigee Edge 的表單參數
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屬性會指出這點
這表示用戶端傳送至 Apigee Edge 的 HTTP 要求中,包含
usernamepassword不允許使用的字元。
檢查表單參數中是否有不允許使用的字元 (如步驟 3 所述),方法如下:
追蹤工具
如要使用「追蹤」工具驗證,請按照下列步驟操作:
實際要求
如要使用實際要求進行驗證,請按照下列步驟操作:
- 如果無法存取向目標伺服器提出的實際要求,請前往「解決方法」。
- 如果您可以存取向 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含有百分比符號 (%),不應以原樣傳遞至表單資料。
- 檢查表單資料內容,看看是否含有不允許使用的字元,例如百分比符號 (
- 在上述兩個範例中,以 HTTP 要求形式傳送至 Apigee Edge 的表單資料含有不允許使用的字元。
- 因此,Apigee Edge 會傳回
500 Internal Server Error, 並顯示錯誤代碼protocol.http.BadFormData。
解析度
- 請確保表單資料或參數的鍵和值中,凡是透過用戶端以 HTTP 要求傳送的特殊字元,一律會按照「 表單資料 - application/x-www-form-urlencoded」一文的說明進行編碼。
- 針對上述範例,您可以按照下列方式修正問題:
範例 #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-urlencoded |
如果仍需要 Apigee 支援團隊協助,請參閱「必須收集診斷資訊」。
必須收集診斷資訊
如果按照上述指示操作後問題仍未解決,請收集下列診斷資訊,然後與 Apigee Edge 支援團隊聯絡:
如果您是公有雲使用者,請提供下列資訊:
- 機構名稱
- 環境名稱
- API Proxy 名稱
- 用於重現
500 Internal Server Error的完整curl指令,以及錯誤代碼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