You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Salesforce Apex调用Redshift Data API遇UnknownOperationException错误求助

Salesforce Apex调用Redshift Data API认证与请求构建问题排查

问题背景

我们是一家咨询公司,正在Salesforce平台上实现调用Amazon Redshift Data API的Apex出站请求认证,最终目标是通过Salesforce的Valence应用执行SQL调用并拉取结果。目前提交带DescribeTable动作的POST请求时,仅收到XML格式的UnknownOperationException错误,需要请求构建的说明和基础示例来排查问题。

核心疑问

  • POST请求中,Action和Version是否应放在查询字符串而非请求体中?
  • 是否需要额外查询字符串参数来正确路由请求?
  • 尽管URL有字符限制,是否应改用GET请求?
  • Content-Type请求头是否需刻意设置,且是否需纳入规范请求?

已尝试方案

  1. 使用Salesforce的命名/外部凭证,通过AWS Signature Version 4协议认证,但不清楚其与请求参数、请求体、请求头的交互方式;
  2. 自行编写认证协议代码,但两种方式均出现相同错误,无法定位问题。

已尝试GET和POST请求均无效,倾向使用POST请求。以下是脱敏后的测试代码及Postman接收的请求头信息:

测试Apex代码

global class JPTestClass {
    public static void jpTestMethod(){
        String POSTMAN_CALLOUT = 'callout:Testing_Postman_API';
        // 指向https://redshift-data.us-east-1.amazonaws.com
        String REDSHIFT_CALLOUT = 'callout:Redshift_Data_API';
        
        send(POSTMAN_CALLOUT);
        send(REDSHIFT_CALLOUT);
    }
    
    public static void send(String callout){
        HttpRequest request = new HttpRequest();

        // POST请求体中的参数
        String payloadString = JSON.serialize(new Map<String, Object>{
                    'Action' => 'DescribeTable',
                    'Version' => '2010-05-08',
                    'ClusterIdentifier' => '<<<XXX>>>', 
                    'ConnectedDatabase' => '<<<XXX>>>',
                    'Database' => '<<<XXX>>>',
                    'MaxResults' => 1000,
                    'NextToken' => '',
                    'Schema' => '<<<XXX>>>',
                    'SecretArn' => '<<<XXX>>>',
                    'Table' => 'salesforce_contacts',
                    'WorkgroupName' => ''
                });
        
        System.debug(payloadString);
        
        request.setEndpoint(callout + '?Action=DescribeTable&Version=2010-05-08');
        request.setMethod('POST');
        
        request.setBody(payloadString);
        
        HttpResponse response = new Http().send(request);
        
        System.debug(response.getBody());
    }
}

Postman接收的请求头

x-forwarded-for: "xxxxxxxxx"
x-forwarded-proto: "xxxxxxxxx"
x-forwarded-port: "xxxxxxxxx"
host: "36b0a2b5-79a5-471e-ac92-06122c76dad2.mock.pstmn.io"
x-amzn-trace-id: "Root=1-639b9d8c-64700ff707de06582eafc6ce"
content-length: "263"
user-agent: "SFDC-Callout/56.0"
sfdc_stack_depth: "1"
accept: "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
authorization: "AWS4-HMAC-SHA256 Credential=<<<ACCESS KEY>>>/20221215/us-east-1/redshift-data/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=0be75a778aa72003cd29140ea52b3db74b6d559078efa382697f8d78b5460b7f"
x-amz-date: "20221215T221956Z"
x-amz-content-sha256: "ec4ae9564eca8bf406807d8ec6305ddbf8435095b269db6f3162b5cfcac4cad8"
accept-encoding: "gzip,deflate"

问题分析与解决方案

核心问题定位

UnknownOperationException的根源是Redshift Data API不接受JSON格式的POST请求体,且请求头未正确设置Content-Type,导致AWS无法识别请求中的操作类型。

疑问解答

  1. Action和Version的位置:
    可放在查询字符串或请求体中,但必须保持格式统一。如果用POST,建议统一放在application/x-www-form-urlencoded格式的请求体里;不要混合JSON参数和查询字符串参数,否则AWS无法正确解析。

  2. 额外查询字符串参数:
    不需要,Redshift Data API仅需正确的服务端点(如https://redshift-data.us-east-1.amazonaws.com),加上Action和Version即可完成路由。

  3. 是否改用GET请求:
    不建议,GET的URL长度限制会影响复杂请求(如长SQL语句),POST更适合这类场景,只要格式正确就能正常工作。

  4. Content-Type请求头的设置:
    必须设置为application/x-www-form-urlencoded,且该头必须纳入AWS SigV4的签名计算(即Salesforce外部凭证的签名Headers列表需包含content-type)。这是解决报错的关键步骤之一。

修正后的Apex代码示例

global class JPTestClass {
    public static void jpTestMethod(){
        String REDSHIFT_CALLOUT = 'callout:Redshift_Data_API';
        send(REDSHIFT_CALLOUT);
    }

    public static void send(String callout){
        HttpRequest request = new HttpRequest();

        // 构造键值对参数,所有值必须为字符串类型
        Map<String, String> params = new Map<String, String>{
            'Action' => 'DescribeTable',
            'Version' => '2010-05-08',
            'ClusterIdentifier' => '<<<XXX>>>', 
            'ConnectedDatabase' => '<<<XXX>>>',
            'Database' => '<<<XXX>>>',
            'MaxResults' => '1000',
            'NextToken' => '',
            'Schema' => '<<<XXX>>>',
            'SecretArn' => '<<<XXX>>>',
            'Table' => 'salesforce_contacts',
            'WorkgroupName' => ''
        };

        // 转换为x-www-form-urlencoded格式的请求体
        String payload = '';
        for(String key : params.keySet()){
            if(payload != '') payload += '&';
            payload += EncodingUtil.urlEncode(key, 'UTF-8') + '=' + EncodingUtil.urlEncode(params.get(key), 'UTF-8');
        }

        request.setEndpoint(callout); // 无需在URL追加Action和Version,已包含在请求体
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        request.setBody(payload);

        HttpResponse response = new Http().send(request);
        System.debug(response.getBody());
    }
}

Salesforce外部凭证配置注意事项

  • 签名版本选择AWS Signature Version 4;
  • 签名Headers必须包含content-type、host、x-amz-date;
  • 服务名称填写redshift-data,区域填写对应的AWS区域(如us-east-1);
  • 确保关联的命名凭证拥有足够的AWS权限(如redshift-data:DescribeTable)。

内容的提问来源于stack exchange,提问作者Beastmanchild

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 07:05:33