Apigee ServiceCallout 400响应转500如何实现原始响应透传
问题描述
使用Apigee代理转发请求时,直连后端API的原始返回为Status Code 400: Bad Request,响应体为空JSON {};但经过Apigee代理处理后,响应被转换为Status Code 500: Internal Server Error,返回Apigee内置错误响应:
{ "fault": { "faultstring": "Execution of ServiceCallout serverPermitGetCallout failed. Reason: ResponseCode 400 is treated as error", "detail": { "errorcode": "steps.servicecallout.ExecutionFailed" } } }
查阅Apigee官方文档中ServiceCallout运行时错误相关章节未找到有效解决方案,尝试配置多种RaiseFault场景均未生效,推测该策略主要适用于请求阶段处理。
现需配置Apigee跳过拦截与消息注入转换逻辑,直接透传后端返回的原始状态码与响应结果,当前相关配置如下:
Proxy Endpoint配置
<Flow name="getServerPermit"> <Condition>(proxy.pathsuffix MatchesPath "/abc**") and (request.verb = "GET")</Condition> <Description/> <Request> <Step> <Name>serverPermitGetCallout</Name> </Step> </Request> <Response> <Step> <Name>serverPermitAssign</Name> </Step> </Response> </Flow>
ServiceCallout策略配置
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ServiceCallout async="false" continueOnError="false" enabled="true" name="abcServerPermitGetCallout"> <DisplayName>serverPermitGetCallout</DisplayName> <Properties/> <Request clearPayload="true" variable="serverPermitGetCalloutRequest"> <Set> <Verb>GET</Verb> </Set> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> </Request> <Response>serverPermitGetCalloutResponse</Response> <HTTPTargetConnection> <Properties/> <URL>https://{abc_endpoint}/api/consume/auth?{request.querystring}</URL> </HTTPTargetConnection> </ServiceCallout>
AssignMessage策略配置
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AssignMessage async="false" continueOnError="false" enabled="true" name="abcServerPermitAssign"> <DisplayName>serverPermitAssign</DisplayName> <Properties/> <AssignTo createNew="true" transport="http" type="response"/> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <Set> <Payload contentType="application/json" variablePrefix="%" variableSuffix="#"> %serverPermitGetCalloutResponse.content# </Payload> </Set> </AssignMessage>
解决方案
问题根因
- ServiceCallout默认将后端返回的4xx/5xx状态码判定为执行失败,你当前配置的
continueOnError="false"会直接触发Apigee内置错误流程,返回500错误,根本不会执行后续Response流中的AssignMessage逻辑。 - 现有AssignMessage策略仅透传了响应体,未同步透传后端原始状态码,即使流程不中断也无法返回正确的400状态。
修复操作
- 修改ServiceCallout策略,将
continueOnError属性值改为true,让后端返回错误状态码时流程不中断,继续执行后续逻辑:
<ServiceCallout async="false" continueOnError="true" enabled="true" name="abcServerPermitGetCallout"> <!-- 其余原有配置保持不变即可 --> </ServiceCallout>
- 修改AssignMessage策略,补充状态码透传逻辑,同时将
createNew改为false直接覆盖现有响应对象,避免生成新的空响应:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AssignMessage async="false" continueOnError="false" enabled="true" name="abcServerPermitAssign"> <DisplayName>serverPermitAssign</DisplayName> <Properties/> <AssignTo createNew="false" transport="http" type="response"/> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <Set> <Payload contentType="application/json" variablePrefix="%" variableSuffix="#"> %serverPermitGetCalloutResponse.content# </Payload> <!-- 透传后端原始状态码 --> <StatusCode>%serverPermitGetCalloutResponse.status.code#</StatusCode> <!-- 如需透传后端响应头可补充对应Headers配置 --> </Set> </AssignMessage>
- (可选精细化控制)如果需要区分ServiceCallout错误类型,仅透传后端返回的业务错误、其他系统错误走默认处理,可以在Proxy Endpoint中新增FaultRule:
<FaultRules> <FaultRule name="透传后端业务错误"> <Condition>(fault.name = "ExecutionFailed") and (errorcode = "steps.servicecallout.ExecutionFailed") and (serverPermitGetCalloutResponse.status.code >= 400)</Condition> <Step> <Name>serverPermitAssign</Name> </Step> </FaultRule> </FaultRules>
配置完成后重新部署代理,即可原样透传后端返回的状态码与响应内容,不会再被Apigee转换为500内置错误。
内容的提问来源于stack exchange,提问作者Michael N
相关产品推荐
相关产品推荐

