<ph type="x-smartling-placeholder"></ph>
您正在查看 Apigee Edge 文档。
转到
Apigee X 文档。 信息
问题
客户端应用收到 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
<ph type="x-smartling-placeholder">
- </ph>
- 如果表单数据较小,则数据以键值对的形式发送,其中包含:
<ph type="x-smartling-placeholder">
- </ph>
- 两个键中的字符已根据 <ph type="x-smartling-placeholder"></ph> 表单 - 第 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"
- 键和值中的任何非字母数字字符均
<ph type="x-smartling-placeholder"></ph>
使用百分比编码,即以三字符组的形式表示这些字符,
%HH
,由一个百分号后跟两位十六进制数字组成 代表特定字符的 ASCII 代码。 - 因此,即使表单数据中允许使用百分号 (
%
), 作为特殊转义序列的开头。因此,如果表单数据需要 键或值中包含百分号 (%
),则应将其传输 为%25,
,它表示百分号的 ASCII 码 (%
) 个字符。
- 如果表单数据较小,则数据以键值对的形式发送,其中包含:
<ph type="x-smartling-placeholder">
- Content-Type: multipart/form-data
如果您要传输大量二进制数据或包含非 ASCII 的文本 那么您可以使用
Content-Type:
multipart/form-data,如 表单 - 第 17.13.4.2 节
可能的原因
当且仅当满足以下所有条件时,才会发生此错误:
- 客户端向 Apigee Edge 发送的 HTTP 请求包含:
<ph type="x-smartling-placeholder">
- </ph>
Content-Type: application/x-www-form-urlencoded
和- 带有百分号 (
%
) 或百分号的表单数据 (%
) 后跟以下不允许使用的无效十六进制字符: <ph type="x-smartling-placeholder"></ph> 表单 - 第 17.13.4.1 节。
Apigee Edge 中的 API 代理可读取包含任何字符的特定形式参数 不允许通过 ExtractVariables 或 AssignMessage 政策。
例如,如果表单数据原样包含百分号 (
%
)(没有 编码)或百分号 (%
),后跟任何无效的十六进制 键和/或值的字符,就会收到此错误。以下是导致此错误的可能原因:
原因 说明 适用的问题排查说明 请求中的表单参数包含禁用字符 客户端作为 HTTP 请求的一部分传递的表单参数包含 禁止使用的字符。 Edge 公有云和私有云用户
常见诊断步骤
使用以下工具/技术之一来诊断此错误:
API 监控
<ph type="x-smartling-placeholder">如需使用 API Monitoring 诊断错误,请执行以下操作:
- <ph type="x-smartling-placeholder"></ph> 以拥有 相应角色。
切换到您要在其中调查问题的单位。
- 导航至分析 >API 监控 >调查页面。
- 选择您观察到错误的具体时间范围。
根据时间绘制错误代码。
<ph type="x-smartling-placeholder">选择错误代码为
protocol.http.BadFormData
的单元格 如下所示:(查看放大图片)
有关错误代码
protocol.http.BadFormData
的信息是 如下所示:(查看放大图片)
点击查看日志,然后展开失败请求对应的行。
- 在日志窗口中,请注意以下详细信息:
<ph type="x-smartling-placeholder">
- </ph>
- 状态代码:
500
- 故障来源:
proxy
- 错误代码:
protocol.http.BadFormData
- 故障政策:
extractvariables/EV-ExtractFormParams
- 状态代码:
- 如果故障来源为
proxy
,则故障代码为protocol.http.BadFormData
和 Fault Policy 为非空,则它 表示错误发生时,错误 Policy 读取或提取表单数据(表单参数)时, 禁止使用的字符。 - 在此示例中,X-Apigee-fault-policy 是
extractvariables/EV- ExtractFormParams,
,这意味着名为 EV-ExtractFormParams 在读取或提取表单时失败 参数。
跟踪工具
<ph type="x-smartling-placeholder">如需使用跟踪工具诊断错误,请执行以下操作:
- 启用跟踪会话
以及:
<ph type="x-smartling-placeholder">
- </ph>
- 等待发生
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 代理的请求流程中。
- 错误值
- 进入跟踪记录中的 AX(记录的 Google Analytics 数据)阶段,然后点击 。
向下滚动到 Stage 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.BadFormData
X-Apigee-fault-source policy
X-Apigee-fault-policy extractvariables/EV-ExtractFormParams
- 在此示例中,X-Apigee-fault-policy 是
extractvariables/EV- ExtractFormParams,
,这表示名为EV-ExtractFormParams
未能读取或提取表单 参数。
NGINX
<ph type="x-smartling-placeholder">如需使用 NGINX 访问日志诊断错误,请执行以下操作:
- 如果您是私有云用户,则可以使用 NGINX 访问日志
确定有关 HTTP
500 Internal Server Error
的关键信息。 查看 NGINX 访问日志:
<ph type="x-smartling-placeholder">/opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
- 搜索是否存在任何带有错误代码的
500
错误protocol.http.BadFormData
(如果问题 或者是否还有任何请求仍失败,500
。 如果您确实在 X-Apigee-fault-code 中找到了任何
500
错误 与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.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
分别是 和 X-Apigee-fault-policy 非空。这表示错误 X-Apigee-fault-policy, 中指出的特定政策 读取或提取表单数据(表单参数),其中包含任何 不允许使用。 - 在此示例中,X-Apigee-fault-policy 是
extractvariables/EV- ExtractFormParams,
,这表示名为EV-ExtractFormParams
未能读取表单 参数。
原因:请求中的表单参数包含不允许使用的字符
诊断
- 按照说明,使用 API 监控、跟踪工具或 NGINX 访问日志确定
500 Internal Server Error
的错误代码、错误来源和错误政策 请参阅常见诊断步骤。 - 如果故障代码为
protocol.http.BadFormData
,则故障来源 值proxy
或policy
,故障政策为非 空白,则表示,中指定的政策 读取或提取表单数据(表单参数)。 - 检查故障政策中指明的政策并确定以下内容
信息:
<ph type="x-smartling-placeholder">
- </ph>
- 来源:确定政策是从 请求或响应。
- 表单参数:确定在
政策。
示例 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
这由以下元素中的
<Pattern>
元素指明:<FormParam>
个元素
这表示表单参数
username
和/或password
作为 HTTP 请求的一部分由客户端传递给 Apigee Edge 包含不允许使用的字符。示例 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
这由
source
属性指明,<Copy>
个元素表单参数:
username
和password
这由
name
属性指明,<FormParam>
个元素
这表示表单参数
username
、password
或 两者均作为 HTTP 请求的一部分由客户端传递给 Apigee Edge,其中包含任何 不允许使用的字符。
检查是否存在不允许的任何字符 第 3 步中确定的表单参数中使用的字符 使用以下任一方法:
跟踪工具
如需使用跟踪工具进行验证,请执行以下操作:
- 如果您已经捕获失败请求的跟踪记录,如 常见的诊断步骤,然后选择 失败的请求。
- 如果您已确定表单参数中包含
不允许使用
第 3 步,则
<ph type="x-smartling-placeholder">
- </ph>
- 进入从客户端收到的请求阶段。
向下滚动到阶段详情部分,并查看 请求内容。
( 查看大图)
- 请注意,在上面的示例中,表单形参
password
包含百分号 (%
)。 - 由于百分号 (
%
) 也用于 <ph type="x-smartling-placeholder"></ph> 百分号编码特殊字符,则不能原样使用 表单数据。 - 因此,Apigee Edge 会以
500 Internal Server Error
(包含错误代码)protocol.http.BadFormData
。
实际请求
如需使用实际请求进行验证,请执行以下操作:
- 如果您无权访问向目标服务器发出的实际请求 然后找到分辨率。
- 如果您有权访问向 Apigee Edge 发出的实际请求,请执行
执行下列步骤:
<ph type="x-smartling-placeholder">
- </ph>
- 检查表单数据内容,看看其中是否包含
不允许使用,例如百分号 (
%
) 或者后跟无效的百分号 (%
) 十六进制字符。示例 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 请求的一部分发送的客户端始终会按照 Form Data - 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 的内容:
使用 <ph type="x-smartling-placeholder"></ph> percent-encoding 表示百分号 (
%
),即将文件修改为%25
,如下所示:xml=<user><username>abc1234@google.com</username><password>qwerty12345!!@#$%25</password></user>
规范
Apigee Edge 应根据以下规范发送表单数据:
规范 |
---|
<ph type="x-smartling-placeholder"></ph> 表单数据 - application/x-www-form-urlencoded |
如果您仍需要 Apigee 支持团队的任何帮助,请参阅必须收集 诊断信息。
必须收集的诊断信息
按照上述说明操作后,如果问题依然存在,请收集以下内容 然后联系 Apigee Edge 支持团队:
如果您是公有云用户,请提供以下信息:
- 组织名称
- 环境名称
- API 代理名称
- 完整的
curl
命令,用于重现500 Internal Server Error
(包含错误代码)protocol.http.BadFormData
- API 请求的跟踪文件
如果您是 Private Cloud 用户,请提供以下信息:
- 观察到失败请求的完整错误消息
- 环境名称
- API 代理软件包
- 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
参考
- <ph type="x-smartling-placeholder"></ph> 表单内容类型
- <ph type="x-smartling-placeholder"></ph> RFC3986,第 2.1 节:百分比编码
- <ph type="x-smartling-placeholder"></ph> 百分比编码
- <ph type="x-smartling-placeholder"></ph> 十六进制字符