我遇到了一个表面上看起来非常可以解决的问题,但内部确实是一个痛苦的世界。我有一个简单的设置,使用 REST API 调用 AWS 中的步骤函数。我需要将主体和一个标头 x-api-key 作为输入参数传递到步骤函数中的状态机。
问题之一是步骤函数使用
StartExecution
进行积分。这不接受标头。 请参阅此处了解更多信息。因此,必须将标头作为输入主体的一部分传递给状态机。
这里有一些方法,应该有效,或者至少可以有效,但不行。
首先,我尝试了这样的映射功能:
{
"stateMachineArn": "arn:aws:states:us-east-1:XXX:stateMachine:XXX",
"headers": {
"apiKey": "$input.params('x-api-key')"
},
"input": "$util.escapeJavaScript($input.json('$')).replaceAll("\\'","'")"
}
或者这个:
{
"stateMachineArn": "arn:aws:states:us-east-1:XXX:stateMachine:XXX",
"input": "$util.escapeJavaScript($input.json('$')).replaceAll("\\'","'")",
"apiKey": "$input.params('x-api-key')"
}
两者都正确获取调用的 x-api-key 和正文(在 API Gateway 日志中确认),并正确转换它们。但是,如上所述,由于 x-api-key 不在输入字符串中,因此在 Step Function 的日志中,它只能看到输入字符串。明确地说,它不仅映射输入字符串,它实际上只接收输入字符串,甚至不接收标头来正确映射它。
这导致了这个潜在的解决方案:
#set($body = $input.json('$'))
#set($token = $input.params().header.get('x-api-token'))
{
"input":"{\"token\":\"$util.escapeJavaScript($token).replaceAll("\\\\'","'")\",\"body\":$util.escapeJavaScript($body).replaceAll("\\\\'", "'")}",
"stateMachineArn": "arn:aws:states:us-east-1:XXX:stateMachine:XXX"
}
此映射模板正确地将标头作为输入字符串的一部分传递。但是,在 API Gateway 中,它会导致
"__type": "com.amazon.coral.service#SerializationException"
错误。我尝试过此映射模板的许多变体。大概有接近两打。这包括尝试以不同方式传递和定义输入字符串等变体。使用 util.toJson
进行编码并避免 #set
,如下所示:
{
"stateMachineArn": "arn:aws:states:us-east-1:XXX:stateMachine:XXX",
"input": "$util.toJson({
\"apiKey\": \"$input.params('x-api-key')\",
\"body\": $input.json('$')
})"
}
或者这个:
#set($apiKey = $input.params('x-api-key'))
#set($body = $input.json('$'))
#set($inputMap = {
"apiKey": $apiKey,
"body": $body
})
{
"stateMachineArn": "arn:aws:states:us-east-1:XXX:stateMachine:XXX",
"input": "$util.toJson($inputMap)"
}
显然我错过了一些东西。或者这里有一种不存在的能力。
我认为您可能已经了解了此映射,但看起来您缺少 json 中 body 元素值周围的引号:
#set($body = $input.json('$'))
#set($token = $input.params().header.get('x-api-token'))
{ "input":"{"token":"$util.escapeJavaScript($token).replaceAll("\'","'")","body":$util.escapeJavaScript($body).replaceAll("\ '", "'")}", "stateMachineArn": "arn:aws:状态:us-east-1:XXX:stateMachine:XXX" }
应该是:
#set($body = $input.json('$'))
#set($token = $input.params().header.get('x-api-token'))
{ "input":"{"token":"$util.escapeJavaScript($token).replaceAll("\'","'")","body":"$util.escapeJavaScript($body).replaceAll(" \'", "'")"}", "stateMachineArn": "arn:aws:状态:us-east-1:XXX:stateMachine:XXX" }
错误会产生您报告的 SerializationException